Giter Club home page Giter Club logo

r2dbc-h2's Introduction

r2dbc-h2's People

Contributors

alexo134 avatar anshlykov avatar boojongmin avatar dimone-kun avatar geirsagberg avatar gmullerb avatar gregturn avatar lukaseder avatar michael-simons avatar mirromutth avatar mp911de avatar mrotteveel avatar nebhale avatar peterjurkovic avatar pull-vert avatar renuevo avatar sdeleuze avatar snicoll avatar thenumberone avatar uaihebert avatar valery1707 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

r2dbc-h2's Issues

Add builder shortcut options for common settings

In embedded mode, it's common to keep the database open as long as the JVM runs, otherwise, the state is discarded if the last connection gets closed. It would be good to have builder shortcuts for .option("DB_CLOSE_DELAY=…") in the sense of closeDelay(Duration) and a command that sets .option("DB_CLOSE_DELAY=-1") to keep the database until the VM exits.

Capture suite of tests for various SQL operations to verify proper H2 API usage

H2Statement.execute() switches on whether or not an INSERT is being issues as to whether it uses Session.update vs. Session.update.

private Flux<H2Result> execute(String sql) {
    if (INSERT.matcher(this.sql).matches()) {
        return this.client.update(sql, this.bindings.bindings)
            .map(result -> H2Result.toResult(result.getGeneratedKeys(), result.getUpdateCount()));
    } else {
        return this.client.query(sql, this.bindings.bindings)
            .map(result -> H2Result.toResult(result, null));
    }
}

H2 throws an exception when query is used without a SELECT so this will fail for commands like CREATE TABLE that exist in Spring Data R2dbc.

Hence, the criteria here should be on SELECT.

Cannot use column label(alias)

I used the column label(alias) using "as" clause, it throws an IllegalArgumentException.
Is specification this behavior?

e.g.

R2dbc r2dbc = new R2dbc(connectionFactory);
r2dbc.useHandle(h -> h.select("SELECT id as value FROM users ORDER BY id")
    .mapResult(result -> result.map((row, rowMetadata) -> row.get("value"))
  )).subscribe(System.out::println);
reactor.core.Exceptions$ErrorCallbackNotImplemented: java.lang.IllegalArgumentException: Column name 'VALUE' does not exist in column names [ID]

Caused by: java.lang.IllegalArgumentException: Column name 'VALUE' does not exist in column names [ID]
	at io.r2dbc.h2.H2Row.getColumn(H2Row.java:117)
	at io.r2dbc.h2.H2Row.get(H2Row.java:72)
	at io.r2dbc.spi.Row.get(Row.java:46)
...

I hope to use column label(alias).

DbException not properly translated

Exceptions raised by H2 are DbException (runtime exceptions). These are not properly translated into R2DBC exceptions.

Reproducer:

H2ConnectionFactory connectionFactory = new H2ConnectionFactory(H2ConnectionConfiguration
		.builder() //
		.inMemory("r2dbc") //
		.username("sa") //
		.password("") //
		.option("DB_CLOSE_DELAY=-1").build());

Flux.from(connectionFactory.create())
		.flatMap(h2Connection -> h2Connection
				.createStatement("SELECT foobar FROM unknown").execute())
		.blockLast();

Stack trace:

Exception in thread "main" org.h2.message.DbException: Tabelle "UNKNOWN" nicht gefunden
Table "UNKNOWN" not found [42102-199]
	at org.h2.message.DbException.get(DbException.java:205)
	at org.h2.message.DbException.get(DbException.java:181)
	at org.h2.command.Parser.readTableOrView(Parser.java:7146)
	at org.h2.command.Parser.readTableFilter(Parser.java:1895)
	at org.h2.command.Parser.parseSelectSimpleFromPart(Parser.java:2641)
	at org.h2.command.Parser.parseSelectSimple(Parser.java:2788)
	at org.h2.command.Parser.parseSelectSub(Parser.java:2636)
	at org.h2.command.Parser.parseSelectUnion(Parser.java:2469)
	at org.h2.command.Parser.parseSelect(Parser.java:2440)
	at org.h2.command.Parser.parsePrepared(Parser.java:814)
	at org.h2.command.Parser.parse(Parser.java:788)
	at org.h2.command.Parser.parse(Parser.java:760)
	at org.h2.command.Parser.prepareCommand(Parser.java:683)
	at org.h2.engine.Session.prepareLocal(Session.java:627)
	at org.h2.engine.Session.prepareCommand(Session.java:565)
	at io.r2dbc.h2.client.SessionClient.createCommand(SessionClient.java:117)
	at io.r2dbc.h2.client.SessionClient.lambda$prepareCommand$3(SessionClient.java:93)
	at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:100)
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1575)
	at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onComplete(FluxDefaultIfEmpty.java:100)
	at reactor.core.publisher.Operators.complete(Operators.java:132)
	at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:122)
	at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:63)
	at reactor.core.publisher.FluxDefaultIfEmpty.subscribe(FluxDefaultIfEmpty.java:42)
	at reactor.core.publisher.FluxMap.subscribe(FluxMap.java:62)
	at reactor.core.publisher.FluxPeek.subscribe(FluxPeek.java:83)
	at reactor.core.publisher.FluxFlatMap.subscribe(FluxFlatMap.java:97)
	at reactor.core.publisher.Flux.subscribe(Flux.java:7922)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:389)
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:121)
	at reactor.core.publisher.FluxJust$WeakScalarSubscription.request(FluxJust.java:99)
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:162)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.onSubscribe(FluxFlatMap.java:335)
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90)
	at reactor.core.publisher.FluxJust.subscribe(FluxJust.java:70)
	at reactor.core.publisher.FluxMapFuseable.subscribe(FluxMapFuseable.java:63)
	at reactor.core.publisher.FluxFlatMap.subscribe(FluxFlatMap.java:97)
	at reactor.core.publisher.Flux.subscribe(Flux.java:7922)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:389)
	at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:114)
	at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2131)
	at reactor.core.publisher.FluxMap$MapSubscriber.request(FluxMap.java:155)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.onSubscribe(FluxFlatMap.java:335)
	at reactor.core.publisher.FluxMap$MapSubscriber.onSubscribe(FluxMap.java:86)
	at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
	at reactor.core.publisher.MonoMap.subscribe(MonoMap.java:55)
	at reactor.core.publisher.FluxSourceMono.subscribe(FluxSourceMono.java:46)
	at reactor.core.publisher.FluxFlatMap.subscribe(FluxFlatMap.java:97)
	at reactor.core.publisher.Flux.blockLast(Flux.java:2389)
	at org.springframework.data.r2dbc.testing.H2TestSupport.main(H2TestSupport.java:84)
	Suppressed: java.lang.Exception: #block terminated with an error
		at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:93)
		at reactor.core.publisher.Flux.blockLast(Flux.java:2390)
		... 1 more
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Tabelle "UNKNOWN" nicht gefunden
Table "UNKNOWN" not found; SQL statement:
SELECT foobar FROM unknown [42102-199]
	at org.h2.message.DbException.getJdbcSQLException(DbException.java:451)
	at org.h2.message.DbException.getJdbcSQLException(DbException.java:427)
	... 51 more

Should be:

R2dbcBadGrammarException

Looking at the code, the mock setup does not match how SessionClient behaves.

Can't connect to h2 db

H2ConnectionFactory.class ->

private static ConnectionInfo getConnectionInfo(H2ConnectionConfiguration configuration)

I don't understand , why you append : to the end of builder!?

StringBuilder sb = new StringBuilder(START_URL).append(configuration.getUrl()).append(":");

So, i always get an error like this

Failed to obtain R2DBC Connection; nested exception is org.h2.message.DbException: A file path that is implicitly relative to the current working directory is not allowed in the database URL \"jdbc:h2:/~testdb:;USER=sa\". Use an absolute path, ~/name, ./name, or the baseDir setting instead. [90011-197]

jdbc:h2:/~testdb: is not correct, but jdbc:h2:/~testdb is correct

Save with H2 in Memory not working properly

I created a small project to setup the database with liquibase and save some data to a db with spring data r2dbc. I tested this with postgres and it works like a charm. With H2 i get an empty Mono back from spring data, even though the data is written to the db. Here is a minimal test-setup in Kotlin with Spring Boot 2.1.2.RELEASE, Spring data r2dbc 1.0.0.M1 and r2dbc Arabba-M7.

@RunWith(SpringRunner::class)
@SpringBootTest
@AutoConfigureWebTestClient
class IntegrationTest {
    private val logger = getLogger(IntegrationTest::class.java)

    @Autowired
    private lateinit var testRepo: TestRepository

    @Test
    fun `save data in h2 memory db`() {
        val testentity = Testentity(null, "Some title", "me! or I!")
        val savedEntity = testRepo.save(testentity)

        StepVerifier.create(savedEntity)
//                .expectNext(testentity.apply {id = 1}) // FIXME: I expect an entity to be returned
                .verifyComplete()

        StepVerifier.create(testRepo.findAll().collectList())
                .consumeNextWith { entityCount -> logger.debug("There are ${entityCount.count()} test entities saved")}
                .verifyComplete()
    }
}

The needed code for the application setup is as follows:

Application Context:

@SpringBootApplication
@EnableR2dbcRepositories
class DatabaseConfig: AbstractR2dbcConfiguration() {
    private val logger: Logger = getLogger(javaClass)
    private var DB_UUID: String = "testdb"

    @Bean
    override fun connectionFactory(): ConnectionFactory {
        val originDataSource = dataSource().unwrap(SimpleDriverDataSource::class.java)

        val config = ConnectionFactories.get(ConnectionFactoryOptions.builder()
                .option(ConnectionFactoryOptions.DRIVER, "h2")
                .option(ConnectionFactoryOptions.PROTOCOL, "mem")
                .option(ConnectionFactoryOptions.DATABASE, DB_UUID)
                .option(ConnectionFactoryOptions.USER, originDataSource.username!!)
                .option(ConnectionFactoryOptions.PASSWORD, originDataSource.password!!)
                .build())

        val queryFormatter = QueryExecutionInfoFormatter.showAll()

        return ProxyConnectionFactory.builder(config)
                    // Log executed query information
                    .onAfterQuery{queryExecInfo ->  queryExecInfo
                            .map(queryFormatter::format)
                            .map(logger::trace)
                            .subscribe()
                    }.build()
    }

    @Bean
    fun converter(mappingContext: RelationalMappingContext, r2dbcCustomConversions: R2dbcCustomConversions): MappingR2dbcConverter {
        return MappingR2dbcConverter(BasicRelationalConverter(mappingContext, r2dbcCustomConversions))
    }

    /**
     * Enable SQL Schema generation via Liquibase. A dataSource is needed for this
     */
    @Bean
    fun dataSource(): DataSource = EmbeddedDatabaseBuilder()
            .setName(DB_UUID)
            .setType(EmbeddedDatabaseType.H2)
            .ignoreFailedDrops(true)
            .build()
}

Entity:

@Entity
data class Testentity(
        @Id
        @GeneratedValue(strategy = AUTO)
        var id: Long?,
        @NotNull
        val title: String,
        @NotNull
        val creator: String
)

Repository:

@Repository
interface TestRepository : ReactiveCrudRepository<Testentity, Long>

Liquibase create table file:

<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd
        http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">

    <changeSet id="1" author="numbernick">
        <createTable tableName="testentity">
            <column name="id" type="BIGINT" autoIncrement="true">
                <constraints primaryKey="true" nullable="false"/>
            </column>
            <column name="title" type="varchar(500)"/>
            <column name="creator" type="varchar(500)">
                <constraints nullable="false"/>
            </column>
        </createTable>
    </changeSet>
</databaseChangeLog>

The output of the test shows that the save-methods works (it persists data), but does not return the saved data:

20-03-2019 13:06:39.346 [main] TRACE d.n.t.r.DatabaseConfig$$EnhancerBySpringCGLIB$$8f98f76c.invoke - Thread:main(1) Connection:1 Transaction:{Create:0 Rollback:0 Commit:0} Success:True Time:11 Type:Statement BatchSize:0 BindingsSize:1 Query:["INSERT INTO testentity (title, creator) VALUES($1, $2)"] Bindings:[(Some title,me! or I!)]
20-03-2019 13:06:39.366 [main] DEBUG d.n.test.reactiveh2.IntegrationTest.accept - There are 1 test entities saved
20-03-2019 13:06:39.366 [main] TRACE d.n.t.r.DatabaseConfig$$EnhancerBySpringCGLIB$$8f98f76c.invoke - Thread:main(1) Connection:2 Transaction:{Create:0 Rollback:0 Commit:0} Success:True Time:10 Type:Statement BatchSize:0 BindingsSize:0 Query:["SELECT id, title, creator FROM testentity"] Bindings:[]

java.util.Date is not supported as bind parameter, only java.sql.Date

.map(client -> new H2Connection(client, new DefaultCodecs()));

Unable to bind java.util.Date. Failure is:

java.lang.IllegalArgumentException: Cannot encode parameter of type java.util.Date
at io.r2dbc.h2.codecs.DefaultCodecs.encode(DefaultCodecs.java:80)
at io.r2dbc.h2.H2Statement.bind(H2Statement.java:75)
at io.r2dbc.h2.H2Statement.bind(H2Statement.java:38)
at org.springframework.data.r2dbc.dialect.IndexedBindMarkers$IndexedBindMarker.bind(IndexedBindMarkers.java:78)
at org.springframework.data.r2dbc.function.DefaultReactiveDataAccessStrategy$DefaultBindableInsert.bind(DefaultReactiveDataAccessStrategy.java:465)
at org.springframework.data.r2dbc.function.BindableOperation.bind(BindableOperation.java:53)
at org.springframework.data.r2dbc.function.DefaultDatabaseClient$DefaultTypedInsertSpec.lambda$exchange$2(DefaultDatabaseClient.java:996)

What is the recommended way to pass/bind java.util.Date?

  • H2Statement is final, so no way to extend
  • H2Statement constr is package visible, so no way to instantiate it and pass custom Codecs in addition to DefaultCodecs
  • DefaultCodecs is also final and no way to customize

IMO, the only option is the client of the Spring r2dbc H2 Repo to convert "somehow:)" manually? Or?

Decoding a null date value fails with NPE

Setup:

CREATE TABLE IF NOT EXISTS PERSON (
  ID            BIGINT      NOT NULL AUTO_INCREMENT PRIMARY KEY,
  BIRTHDATE     DATE
);

INSERT INTO Person(ID)            VALUES (1);

Consuming the result of a SELECT * FROM PERSON with row.get("birthdate") fails with:

java.lang.NullPointerException: null
	at io.r2dbc.h2.codecs.DateCodec.transform(DateCodec.java:59) ~[r2dbc-h2-0.8.0.M8.jar:na]
	at io.r2dbc.h2.codecs.DateCodec.doDecode(DateCodec.java:44) ~[r2dbc-h2-0.8.0.M8.jar:na]
	at io.r2dbc.h2.codecs.DateCodec.doDecode(DateCodec.java:31) ~[r2dbc-h2-0.8.0.M8.jar:na]
	at io.r2dbc.h2.codecs.AbstractCodec.decode(AbstractCodec.java:60) ~[r2dbc-h2-0.8.0.M8.jar:na]
	at io.r2dbc.h2.codecs.DefaultCodecs.decode(DefaultCodecs.java:73) ~[r2dbc-h2-0.8.0.M8.jar:na]
	at io.r2dbc.h2.H2Row.get(H2Row.java:79) ~[r2dbc-h2-0.8.0.M8.jar:na]
	at io.r2dbc.spi.Row.get(Row.java:63) ~[r2dbc-spi-0.8.0.M8.jar:na]
	at org.springframework.data.r2dbc.convert.MappingR2dbcConverter$RowParameterValueProvider.getParameterValue(MappingR2dbcConverter.java:426) ~[spring-data-r2dbc-1.0.0.M2.jar:1.0.0.M2]

Accept bind query param with integer index

Current scenario

Right now, it is only possible to receive String as bind param:

public H2Statement bind(Object identifier, Object value) {
Assert.requireNonNull(identifier, "identifier must not be null");
Assert.requireType(identifier, String.class, "identifier must be a String");
return bind(getIndex((String) identifier), value);
}

This code accept as valid input:

  • bind("?1", 100)
  • bind("$1", 100)

What we need to improve

We should support integers as bind params, like:

  • bind(0, 100)

Requirements are:

Make sure docs are consistent with implementation for bind prefix

Using r2bdc-h2-1.0.0.M7 I have to use $ rather than ? (as README suggests) in order for select binding to function correctly.

For example:

public Mono<Policies> findServiceInstancePolicyById(String id) {
		String index = "$1";
		String selectServiceInstancePolicy = "select pk, id, description, from_datetime, from_duration, organization_whitelist from service_instance_policy where id = " + index;
		List<ServiceInstancePolicy> serviceInstancePolicies = new ArrayList<>();
		return
			Flux
				.from(client.execute().sql(selectServiceInstancePolicy)
						.bind(index, id)
						.map((row, metadata) ->
							ServiceInstancePolicy
								.builder()
									.pk(row.get("pk", Long.class))
									.id(row.get("id", String.class))
									.description(row.get("description", String.class))
									.fromDateTime(row.get("from_datetime", Timestamp.class) != null ? row.get("from_datetime", Timestamp.class).toLocalDateTime() : null)
									.fromDuration(row.get("from_duration", String.class) != null ? Duration.parse(row.get("from_duration", String.class)): null)
									.organizationWhiteList(row.get("organization_whitelist", String.class) != null ? new HashSet<String>(Arrays.asList(row.get("organization_whitelist", String.class).split("\\s*,\\s*"))): new HashSet<>())
									.build())
						.all())
				.map(sp -> serviceInstancePolicies.add(sp))
				.then(Mono.just(new Policies(Collections.emptyList(), serviceInstancePolicies)))
				.flatMap(p -> p.isEmpty() ? Mono.empty(): Mono.just(p));
	}

Clean out @author tags

The project has adopted a no-author tag policy on all documentation. IDEs like to bring them in by default, so we need to clean them out.

Binary field data auto converting to null binding when using ReactiveCrudRepository.

When creating a table with a BLOB and a supporting entity class coupled with a ReactiveCrudRepository interface, the byte[] field will not save to the database. The resulting error is: java.lang.IllegalArgumentException: Cannot encode null parameter of type [Ljava.lang.Byte;)

Tracing into a unit test, the type of the binary field in converted to java.lang.Byte[], but the codec is looking for byte[] (i.e. type [b).

I've provided a simple project that can recreate the issue with a simple unit test.

https://github.com/gm2552/r2dbc-binarydata-sample.git

Add support for GEOMETRY type

Currently there is no support for spatial geometry type:

In the meantime, anyone having same requirement can:

CREATE TABLE theTable (
  location GEOMETRY(POINT) NOT NULL,
);
final WKTReader wktReader = new WKTReader();
r2dbc.inTransaction(handle -> handle
  .select("SELECT CAST(location AS VARCHAR) AS loc FROM theTable")
  .mapRow(row -> row.get("loc", String.class))
  .flatMap(loc -> Mono.create(sink -> {
    try {
      sink.success(wktReader.read(loc));
    }
    catch (Exception ex) {
      sink.error(ex);
    }
  })));

H2Statement.execute(sql) checks the composite statement, not the local one before executing

    private Flux<H2Result> execute(String sql) {
        if (INSERT.matcher(this.sql).matches()) {
            return this.client.update(sql, this.bindings.bindings)
                .map(result -> H2Result.toResult(result.getGeneratedKeys(), result.getUpdateCount()));
        } else {
            return this.client.query(sql, this.bindings.bindings)
                .map(result -> H2Result.toResult(result, null));
        }
    }

Since it's possible to have multiple types of statements chained together via ";", the check should be done against sql, not this.sql.

This type of leakage would be prevented if execute(sql) was static.

Support to embedded H2?

Currently the SessionClient enforces SessionRemote, are there any way to use the normal Session?

Add support for BLOB/CLOB types.

Project main page states "This driver provides the following features: Read and write support for all data types except LOB types (e.g. BLOB, CLOB)"

What is the plan to support for org.h2.value.ValueLobDb?

  • yes: great! when it might be expected?
  • no: what are the obstacles/concerns?

My use-case is JPA_H2_Repo writes java.Map as CLOB/ValueLobDb and then it's not possible to read it by R2DBC_H2_Repo.

Thanks!

Fix select bind incompatibility with H2 1.4.198

Using r2dbc-h2-1.0.0.M7 I see that select bindings fail with

java.lang.NoSuchMethodError: org.h2.result.ResultInterface.getColumnType(I)I
    at io.r2dbc.h2.H2ColumnMetadata.toColumnMetadata(H2ColumnMetadata.java:127) ~[r2dbc-h2-1.0.0.M7.jar:na]
    at io.r2dbc.h2.H2RowMetadata.getColumnMetadatas(H2RowMetadata.java:106) ~[r2dbc-h2-1.0.0.M7.jar:na]
    at io.r2dbc.h2.H2RowMetadata.toRowMetadata(H2RowMetadata.java:99) ~[r2dbc-h2-1.0.0.M7.jar:na]
    at io.r2dbc.h2.H2Result.toResult(H2Result.java:86) ~[r2dbc-h2-1.0.0.M7.jar:na]

Should not decode null integer value to 0

Use r2dbc-h2-0.8.0.M8

create table t(id integer primary key, v integer)
insert into t(id, v) values (1, null);
StepVerifier.create(
  Mono.from(connectionFactory.create())
    .flatMap(c -> Mono.from(c.createStatement("select * from t where id = 1").execute()))
    .flatMap(result -> Mono.from(result.map((row, rowMetadata) -> row.get("v", Integer.class))))
).expectNext((Integer) null).verifyComplete();

Error:

expectation "expectNext(null)" failed (expected value: null; actual value: 0)

Pick up known H2 configuration properties

H2 support a lot of config options. Instead of being required to specify these via .option("CIPHER=AES") and hoping no character harms the URL format, it would make sense to capture these via ConnectionFactoryOptions and inspect the R2DBC url for these.

In H2ConnectionConfiguration, we should introduce an options map that allows specifying these options. ConnectionInfo accepts a Properties object that can be used to notify H2 about these options.

See also: http://www.h2database.com/html/features.html#database_url

Support to decode primitive integers (and other primitives?)

I just ran into an issue trying to call row.get(…, int.class) with the error message saying int is not a supported type. Switching to Integer.class got it working but I wonder whether we should be able to decode primitives OOTB to avoid boxing.

Add configuration for DB Close Delay

We should provide a configuration property to set DB Close delay. Using H2 with Spring Data R2DBC opens/closes a connection each time we invoke an operation. Closing a in-memory connection causes that all previous state (tables, inserted data) is lost. The current workaround is using url("mem:test;DB_CLOSE_DELAY=10") via H2ConnectionConfiguration.builder().

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.