Giter VIP home page Giter VIP logo

r2dbc-mssql's Introduction

r2dbc-mssql's People

Contributors

dajudge avatar gregturn avatar lhaatveit avatar mirromutth avatar mp911de avatar mrotteveel avatar nebhale avatar nhajratw avatar spring-operator avatar squiry avatar thankuswr avatar uaihebert 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  avatar  avatar

r2dbc-mssql's Issues

Getting java.lang.IllegalStateException: Collation not available when querying the database.

Hi all. I'm trying to write a basic example of the Spring R2DBC using a SQL Server database.
Whenever I try to query it, I get the following exception: java.lang.IllegalStateException: Collation not available.
Here are my classes:

My ConnectionFactoryConfiguration:

@Configuration
class ConnectionFactoryConfiguration {

	@Bean
	DatabaseClient databaseClient() {
		return DatabaseClient.create(connectionFactory());
	}

	@Bean
	public ConnectionFactory connectionFactory() {
		MssqlConnectionConfiguration config = MssqlConnectionConfiguration.builder() //
			.host("localhost")
			.port(1434)
			.database("pizza")
			.username("test")
			.password("test")
			.build();
		return new MssqlConnectionFactory(config);
	}
}

My repository (I'm not using Spring Data, though):

@Repository
public class ManualPizzaRepository {

    private final ConnectionFactory connectionFactory;

    public ManualPizzaRepository(ConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
    }

    Mono<Void> deleteById(Integer id) {
        return this.connection()
            .flatMapMany(c -> c.createStatement("delete from pizza where id = $1")
                .bind("$1", id)
                .execute())
            .then();
    }

    Flux<Pizza> findAll() {
        return this.connection()
            .flatMapMany(connection ->
                Flux.from(connection.createStatement("select * from pizza").execute())
                    .flatMap(r ->
                        r.map((row, rowMetadata) ->
                            new Pizza(row.get("id", Integer.class), row.get("flavor", String.class)))));
    }

    Flux<Pizza> save(Pizza pizza) {
        Flux<? extends Result> flux = this.connection().flatMapMany(conn -> conn.createStatement("insert into pizza (flavor) values ($1)")
            .bind("$1", pizza.getFlavor())
            .add()
            .execute());

        return flux.switchMap(x -> Flux.just(new Pizza(pizza.getId(), pizza.getFlavor())));
    }

    private Mono<Connection> connection() {
        return Mono.from(this.connectionFactory.create());
    }

}

My model class:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Pizza {

    @Id
    private Integer id;
    private String flavor;

}

My test class (where I perform the call that's throwing the exception):

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ConnectionFactoryConfiguration.class, ManualPizzaRepository.class})
public class ReactiveSqlSqlserverApplicationTests {

	@Autowired
	ManualPizzaRepository pizzas;

	@Autowired
	DatabaseClient databaseClient;

	@Test
	public void testAllManual() {
		Flux<Void> deleteAll = this.pizzas.findAll().flatMap(pizza -> this.pizzas.deleteById(pizza.getId()));
		StepVerifier.create(deleteAll).expectNextCount(0).verifyComplete();

		Flux<Pizza> savePizzas = Flux.just("Mozzarella", "Pepperoni", "Margherita")
			.map(flavor -> new Pizza(null, flavor))
			.flatMap(pizza -> this.pizzas.save(pizza));
		StepVerifier.create(savePizzas).expectNextCount(3).verifyComplete();

		Flux<Pizza> findAll = this.pizzas.findAll();
		StepVerifier.create(findAll).expectNextCount(3).verifyComplete();

	}
}

My database configuration:
database options
database options 2

Stack trace of the exception:

2019-03-15 13:31:34.058  WARN 8292 --- [actor-tcp-nio-1] i.r2dbc.mssql.client.ReactorNettyClient  : Failed onEnvironmentChange() in io.r2dbc.mssql.client.ReactorNettyClient$CollationListener@1680fe48

io.r2dbc.mssql.message.tds.ProtocolException: null
	at io.r2dbc.mssql.message.type.Collation.decode(Collation.java:127) ~[r2dbc-mssql-1.0.0.M7.jar:1.0.0.M7]
	at io.r2dbc.mssql.client.ReactorNettyClient$CollationListener.onEnvironmentChange(ReactorNettyClient.java:429) ~[r2dbc-mssql-1.0.0.M7.jar:1.0.0.M7]
	at io.r2dbc.mssql.client.ReactorNettyClient.lambda$new$1(ReactorNettyClient.java:106) ~[r2dbc-mssql-1.0.0.M7.jar:1.0.0.M7]
	at io.r2dbc.mssql.client.ReactorNettyClient.lambda$handleMessage$19(ReactorNettyClient.java:363) ~[r2dbc-mssql-1.0.0.M7.jar:1.0.0.M7]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:177) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:113) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:826) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:826) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:275) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:849) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drainSync(FluxFlattenIterable.java:564) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drain(FluxFlattenIterable.java:635) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.request(FluxFlattenIterable.java:266) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:1878) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:1752) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.onSubscribe(FluxFlattenIterable.java:208) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.core.publisher.FluxGenerate.subscribe(FluxGenerate.java:83) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.core.publisher.FluxFlattenIterable.subscribe(FluxFlattenIterable.java:109) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.core.publisher.Flux.subscribe(Flux.java:7777) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:442) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onNext(FluxConcatMap.java:244) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
	at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:205) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
	at reactor.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:321) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
	at reactor.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:319) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
	at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:141) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.r2dbc.mssql.client.ssl.TdsSslHandler.channelRead(TdsSslHandler.java:374) ~[r2dbc-mssql-1.0.0.M7.jar:1.0.0.M7]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1408) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:677) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:612) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:529) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:491) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:905) ~[netty-common-4.1.33.Final.jar:4.1.33.Final]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_201]
Caused by: java.io.UnsupportedEncodingException: Windows collation not supported: D000
	at io.r2dbc.mssql.message.type.Collation.getEncodingFromLCID(Collation.java:226) ~[r2dbc-mssql-1.0.0.M7.jar:1.0.0.M7]
	at io.r2dbc.mssql.message.type.Collation.<init>(Collation.java:89) ~[r2dbc-mssql-1.0.0.M7.jar:1.0.0.M7]
	at io.r2dbc.mssql.message.type.Collation.decode(Collation.java:125) ~[r2dbc-mssql-1.0.0.M7.jar:1.0.0.M7]
	... 51 common frames omitted


java.lang.AssertionError: expectation "expectComplete" failed (expected: onComplete(); actual: onError(java.lang.IllegalStateException: Collation not available))

	at reactor.test.ErrorFormatter.assertionError(ErrorFormatter.java:105)
	at reactor.test.ErrorFormatter.failPrefix(ErrorFormatter.java:94)
	at reactor.test.ErrorFormatter.fail(ErrorFormatter.java:64)
	at reactor.test.ErrorFormatter.failOptional(ErrorFormatter.java:79)
	at reactor.test.DefaultStepVerifierBuilder.lambda$expectComplete$4(DefaultStepVerifierBuilder.java:323)
	at reactor.test.DefaultStepVerifierBuilder$SignalEvent.test(DefaultStepVerifierBuilder.java:2112)
	at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onSignal(DefaultStepVerifierBuilder.java:1408)
	at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onExpectation(DefaultStepVerifierBuilder.java:1356)
	at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onError(DefaultStepVerifierBuilder.java:1030)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.checkTerminated(FluxFlatMap.java:790)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.drainLoop(FluxFlatMap.java:560)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.drain(FluxFlatMap.java:540)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.onError(FluxFlatMap.java:412)
	at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onError(MonoFlatMapMany.java:243)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.checkTerminated(FluxFlatMap.java:790)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.drainLoop(FluxFlatMap.java:560)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.drain(FluxFlatMap.java:540)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.onError(FluxFlatMap.java:412)
	at reactor.core.publisher.Operators.error(Operators.java:181)
	at reactor.core.publisher.FluxDefer.subscribe(FluxDefer.java:50)
	at reactor.core.publisher.FluxFlatMap.subscribe(FluxFlatMap.java:97)
	at reactor.core.publisher.Flux.subscribe(Flux.java:7777)
	at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onNext(MonoFlatMapMany.java:184)
	at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:114)
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1505)
	at reactor.core.publisher.MonoDelayUntil$DelayUntilCoordinator.signal(MonoDelayUntil.java:211)
	at reactor.core.publisher.MonoDelayUntil$DelayUntilTrigger.onComplete(MonoDelayUntil.java:290)
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:252)
	at reactor.core.publisher.FluxHandle$HandleSubscriber.onComplete(FluxHandle.java:207)
	at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:128)
	at reactor.core.publisher.FluxFilter$FilterConditionalSubscriber.onNext(FluxFilter.java:240)
	at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:826)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.drainLoop(FluxFlatMap.java:664)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.drain(FluxFlatMap.java:540)
	at reactor.core.publisher.FluxFlatMap$FlatMapInner.onNext(FluxFlatMap.java:940)
	at reactor.core.publisher.FluxReplay$UnboundedReplayBuffer.replayFused(FluxReplay.java:626)
	at reactor.core.publisher.FluxReplay$UnboundedReplayBuffer.replay(FluxReplay.java:656)
	at reactor.core.publisher.FluxReplay$ReplaySubscriber.onNext(FluxReplay.java:1161)
	at reactor.core.publisher.FluxWindowPredicate$WindowFlux.drainRegular(FluxWindowPredicate.java:636)
	at reactor.core.publisher.FluxWindowPredicate$WindowFlux.drain(FluxWindowPredicate.java:714)
	at reactor.core.publisher.FluxWindowPredicate$WindowFlux.onNext(FluxWindowPredicate.java:756)
	at reactor.core.publisher.FluxWindowPredicate$WindowPredicateMain.onNext(FluxWindowPredicate.java:227)
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:192)
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:192)
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:192)
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:192)
	at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:113)
	at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:826)
	at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:826)
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:275)
	at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:849)
	at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drainSync(FluxFlattenIterable.java:564)
	at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drain(FluxFlattenIterable.java:635)
	at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.request(FluxFlattenIterable.java:266)
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:1878)
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:1752)
	at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.onSubscribe(FluxFlattenIterable.java:208)
	at reactor.core.publisher.FluxGenerate.subscribe(FluxGenerate.java:83)
	at reactor.core.publisher.FluxFlattenIterable.subscribe(FluxFlattenIterable.java:109)
	at reactor.core.publisher.Flux.subscribe(Flux.java:7777)
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:442)
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onNext(FluxConcatMap.java:244)
	at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:205)
	at reactor.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:321)
	at reactor.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:319)
	at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:141)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
	at io.r2dbc.mssql.client.ssl.TdsSslHandler.channelRead(TdsSslHandler.java:374)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1408)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:677)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:612)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:529)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:491)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:905)
	at java.lang.Thread.run(Thread.java:748)
	Suppressed: java.lang.IllegalStateException: Collation not available
		at io.r2dbc.mssql.client.Client.lambda$getRequiredCollation$0(Client.java:85)
		at java.util.Optional.orElseThrow(Optional.java:290)
		at io.r2dbc.mssql.client.Client.getRequiredCollation(Client.java:85)
		at io.r2dbc.mssql.CursoredQueryMessageFlow.exchange(CursoredQueryMessageFlow.java:112)
		at io.r2dbc.mssql.SimpleCursoredMssqlStatement.lambda$execute$1(SimpleCursoredMssqlStatement.java:58)
		at reactor.core.publisher.FluxDefer.subscribe(FluxDefer.java:46)
		... 73 more

UPDATE: Forgot to add my POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>reactive-sql-sqlserver</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>reactive-sql-sqlserver</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-r2dbc</artifactId>
            <version>1.0.0.M1</version>
        </dependency>
        <dependency>
            <groupId>io.r2dbc</groupId>
            <artifactId>r2dbc-mssql</artifactId>
            <version>1.0.0.M7</version>
        </dependency>
        <dependency>
            <groupId>io.r2dbc</groupId>
            <artifactId>r2dbc-spi</artifactId>
            <version>1.0.0.M7</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Thanks in advance for your help.

Propagate decoding exception to the receiver Publisher

Decoding exceptions are not propagated to the resulting Publisher but bubbled up to the netty handler pipeline. Decode exceptions should be propagated down to the receiver and should also close the connection as decoding issues typically destroy the connection state.

Example:

16:14:19.862 reactor-tcp-nio-1 reactor.core.publisher.Operators Operator called default onErrorDropped
reactor.core.Exceptions$BubblingException: java.lang.IllegalArgumentException: minimumReadableBytes: -1 (expected: >= 0)
	at reactor.core.Exceptions.bubble(Exceptions.java:154)
	at reactor.core.publisher.FluxGenerate$GenerateSubscription.poll(FluxGenerate.java:364)
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.poll(FluxOnAssembly.java:470)
	at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drainSync(FluxFlattenIterable.java:498)
	at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drain(FluxFlattenIterable.java:635)
	at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.request(FluxFlattenIterable.java:266)
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.request(FluxOnAssembly.java:458)
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:1849)
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:1723)
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onSubscribe(FluxOnAssembly.java:442)
	at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.onSubscribe(FluxFlattenIterable.java:208)
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onSubscribe(FluxOnAssembly.java:442)
	at reactor.core.publisher.FluxGenerate.subscribe(FluxGenerate.java:83)
	at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:164)
	at reactor.core.publisher.FluxFlattenIterable.subscribe(FluxFlattenIterable.java:109)
	at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:164)
	at reactor.core.publisher.Flux.subscribe(Flux.java:7734)
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:442)
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onNext(FluxConcatMap.java:244)
	at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:211)
	at reactor.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:327)
	at reactor.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:310)
	at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:141)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
	at io.r2dbc.mssql.client.ssl.TdsSslHandler.channelRead(TdsSslHandler.java:374)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:648)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:583)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:500)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:462)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
	at java.lang.Thread.run(Thread.java:748)
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Assembly trace from producer [reactor.core.publisher.FluxFlattenIterable] :
	reactor.core.publisher.Flux.flatMapIterable(Flux.java:4853)
	reactor.core.publisher.Flux.flatMapIterable(Flux.java:4828)
	io.r2dbc.mssql.client.StreamDecoder.decode(StreamDecoder.java:123)
	io.r2dbc.mssql.client.ReactorNettyClient.lambda$new$4(ReactorNettyClient.java:177)
	reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:368)
	reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onNext(FluxConcatMap.java:244)
	reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:211)
	reactor.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:327)
	reactor.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:310)
	reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:141)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
	io.r2dbc.mssql.client.ssl.TdsSslHandler.channelRead(TdsSslHandler.java:374)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965)
	io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
	io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:648)
	io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:583)
	io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:500)
	io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:462)
	io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
Error has been observed by the following operator(s):
	|_	Flux.flatMapIterable ⇢ io.r2dbc.mssql.client.StreamDecoder.decode(StreamDecoder.java:123)

Caused by: java.lang.IllegalArgumentException: minimumReadableBytes: -1 (expected: >= 0)
	at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1418)
	at io.netty.buffer.AbstractByteBuf.skipBytes(AbstractByteBuf.java:971)
	at io.r2dbc.mssql.message.token.RowToken.canDecodeColumn(RowToken.java:125)
	at io.r2dbc.mssql.message.token.RowToken.canDecode(RowToken.java:95)
	at io.r2dbc.mssql.message.token.Tabular.lambda$decodeFunction$0(Tabular.java:184)
	at io.r2dbc.mssql.message.token.Tabular$TabularDecoder.decode(Tabular.java:372)
	at io.r2dbc.mssql.client.ConnectionState$4.lambda$decoder$1(ConnectionState.java:194)
	at io.r2dbc.mssql.client.StreamDecoder.lambda$decode$1(StreamDecoder.java:94)
	at reactor.core.publisher.FluxGenerate$GenerateSubscription.poll(FluxGenerate.java:347)
	... 48 common frames omitted
16:14:19.863 reactor-tcp-nio-1 io.netty.channel.AbstractChannelHandlerContext An exception '{}' [enable DEBUG level for full stacktrace] was thrown by a user handler's exceptionCaught() method while handling the following exception:
reactor.core.Exceptions$BubblingException: java.lang.IllegalArgumentException: minimumReadableBytes: -1 (expected: >= 0)
	at reactor.core.Exceptions.bubble(Exceptions.java:154)
	at reactor.core.publisher.FluxGenerate$GenerateSubscription.poll(FluxGenerate.java:364)
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.poll(FluxOnAssembly.java:470)
	at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drainSync(FluxFlattenIterable.java:498)
	at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drain(FluxFlattenIterable.java:635)
	at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.request(FluxFlattenIterable.java:266)
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.request(FluxOnAssembly.java:458)
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:1849)
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:1723)
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onSubscribe(FluxOnAssembly.java:442)
	at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.onSubscribe(FluxFlattenIterable.java:208)
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onSubscribe(FluxOnAssembly.java:442)
	at reactor.core.publisher.FluxGenerate.subscribe(FluxGenerate.java:83)
	at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:164)
	at reactor.core.publisher.FluxFlattenIterable.subscribe(FluxFlattenIterable.java:109)
	at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:164)
	at reactor.core.publisher.Flux.subscribe(Flux.java:7734)
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:442)
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onNext(FluxConcatMap.java:244)
	at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:211)
	at reactor.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:327)
	at reactor.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:310)
	at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:141)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
	at io.r2dbc.mssql.client.ssl.TdsSslHandler.channelRead(TdsSslHandler.java:374)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:648)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:583)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:500)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:462)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
	at java.lang.Thread.run(Thread.java:748)
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Assembly trace from producer [reactor.core.publisher.FluxFlattenIterable] :
	reactor.core.publisher.Flux.flatMapIterable(Flux.java:4853)
	reactor.core.publisher.Flux.flatMapIterable(Flux.java:4828)
	io.r2dbc.mssql.client.StreamDecoder.decode(StreamDecoder.java:123)
	io.r2dbc.mssql.client.ReactorNettyClient.lambda$new$4(ReactorNettyClient.java:177)
	reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:368)
	reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onNext(FluxConcatMap.java:244)
	reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:211)
	reactor.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:327)
	reactor.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:310)
	reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:141)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
	io.r2dbc.mssql.client.ssl.TdsSslHandler.channelRead(TdsSslHandler.java:374)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965)
	io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
	io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:648)
	io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:583)
	io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:500)
	io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:462)
	io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
Error has been observed by the following operator(s):
	|_	Flux.flatMapIterable ⇢ io.r2dbc.mssql.client.StreamDecoder.decode(StreamDecoder.java:123)

Caused by: java.lang.IllegalArgumentException: minimumReadableBytes: -1 (expected: >= 0)
	at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1418)
	at io.netty.buffer.AbstractByteBuf.skipBytes(AbstractByteBuf.java:971)
	at io.r2dbc.mssql.message.token.RowToken.canDecodeColumn(RowToken.java:125)
	at io.r2dbc.mssql.message.token.RowToken.canDecode(RowToken.java:95)
	at io.r2dbc.mssql.message.token.Tabular.lambda$decodeFunction$0(Tabular.java:184)
	at io.r2dbc.mssql.message.token.Tabular$TabularDecoder.decode(Tabular.java:372)
	at io.r2dbc.mssql.client.ConnectionState$4.lambda$decoder$1(ConnectionState.java:194)
	at io.r2dbc.mssql.client.StreamDecoder.lambda$decode$1(StreamDecoder.java:94)
	at reactor.core.publisher.FluxGenerate$GenerateSubscription.poll(FluxGenerate.java:347)
	... 48 common frames omitted

Reduce object allocations

We should consider caching for Length and lazily create row consumers instead of pre-preparing row count and row data sequences.

Add FluxDiscardOnCancel operator

We need a Flux operator that allows discarding data signals (except terminal signals) when a downstream Subscriber cancels the subscription. A typical example is:

result.map((row, metadata)-> …).next();

Canceling the subscription can leave data signals non-consumed so the protocol state gets mixed up:

  1. No demand, so no further reads on the channel
  2. Consumers of different windows might receive the remaining frames

FluxDiscardOnCancel would behave ideally:

  • Passthrough signals by default
  • On cancellation:
    1. request(Long.MAX_VALUE)
    2. discard data signal
    3. propagate terminal signals

/cc @nebhale @simonbasle @smaldini @gregturn

Fix ConnectionFactories usage example in readme

The example

ConnectionFactory connectionFactory = ConnectionFactories.get(ConnectionFactoryOptions.builder()
...
    .build());

Mono<Connection> connection = connectionFactory.create();

does not work because ConnectionFactory returns Publisher<…> and not Mono<…>.

Add support for varchar(max) and nvarchar(max)

varchar(max) and nvarchar(max) are PLP (Partially Length-Prefixed) Data Types and they are not supported by the driver yet.

Using a varchar(max) column typically results in a decoding exception:

java.lang.IllegalArgumentException: minimumReadableBytes: -1 (expected: >= 0)
	at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1418)
	at io.netty.buffer.AbstractByteBuf.skipBytes(AbstractByteBuf.java:971)
	at io.r2dbc.mssql.message.token.RowToken.canDecodeColumn(RowToken.java:125)
	at io.r2dbc.mssql.message.token.RowToken.canDecode(RowToken.java:95)
	at io.r2dbc.mssql.message.token.Tabular.lambda$decodeFunction$0(Tabular.java:184)
	at io.r2dbc.mssql.message.token.Tabular$TabularDecoder.decode(Tabular.java:372)

Executing a parametrized Statement twice fails

Reusing a parametrized statement (multiple subscriptions) fails because bound values (ref-counted) are attempted to be released.

We should either reject the execution early or allow execution multiple times.

Add support for parametrized batches

Statement.add() allows the creation of multiple bindings for a prepared statement and so execution of the prepared statements with various bindings ("Prepared Statement Batch"). We should add support for this mode of execution.

The difficulty is to consume/retain protocol state to make sure the next batch is sent when the previous one's response is fully consumed.

Tabular decode function retains previous column metadata

Executing a Tabular decode retains previous column metadata (ColumnMetadataToken) token and does not replace it when receiving a subsequent token. This leads to decoding errors of row metadata.

We need to check after metadata decoding whether the token is qualified to replate a potential previous metadata token.

Add configurable fetch size to MssqlStatement

We should allow the configuration of fetchSize on Statement level to supply a fetch size for cursored execution and to override the cursored execution preference. Setting fetch size to zero enforces direct execution, setting it to a non-negative non-zero value enforces cursored execution.

Reduce dependencies

Currently, this project depends on reactor-extra, Spring Boot JDBC starter, and transitively on netty-codec-http (1+2), and netty-handler-proxy.

We should eliminate dead dependencies.

Add benchmark suites

We should provide a suite of benchmarks to measure the performance and throughput of the driver. Metrics that we should gather:

Offline metrics

  • Codec throughput
  • Statement creation
  • Query parsing (ParsedQuery)

Integration metrics

  • Query execution using SQLBATCH and RPC (Non-parametrized Cursored, Parametrized Direct, Parametrized Cursored)

Query-Subscribers of Client.exchange(…) remain subscribed

When issuing a query, downstream subscribers of query flows remain subscribed. This causes duplication of signals and a lot of dropped notifications. We should unsubscribe from the message exchange after completing a query execution.

Add EnumCodec

When trying to save an object that contains an enum value, I got the following error:

java.lang.IllegalArgumentException: Cannot encode [MY_VALUE] parameter of type [com.mycompany.MyEnum]
	at io.r2dbc.mssql.codec.DefaultCodecs.encode(DefaultCodecs.java:92) ~[r2dbc-mssql-1.0.0.M7.jar:1.0.0.M7]
	at io.r2dbc.mssql.PreparedMssqlStatement.bind(PreparedMssqlStatement.java:155) ~[r2dbc-mssql-1.0.0.M7.jar:1.0.0.M7]
	at io.r2dbc.mssql.PreparedMssqlStatement.bind(PreparedMssqlStatement.java:57) ~[r2dbc-mssql-1.0.0.M7.jar:1.0.0.M7]
	at org.springframework.data.r2dbc.dialect.NamedBindMarkers$NamedBindMarker.bind(NamedBindMarkers.java:105) ~[spring-data-r2dbc-1.0.0.M1.jar:1.0.0.M1]
	at org.springframework.data.r2dbc.function.DefaultReactiveDataAccessStrategy$DefaultBindableInsert.bind(DefaultReactiveDataAccessStrategy.java:465) ~[spring-data-r2dbc-1.0.0.M1.jar:1.0.0.M1]
	at org.springframework.data.r2dbc.function.BindableOperation.bind(BindableOperation.java:53) ~[spring-data-r2dbc-1.0.0.M1.jar:1.0.0.M1]
	at org.springframework.data.r2dbc.function.DefaultDatabaseClient$DefaultTypedInsertSpec.lambda$exchange$2(DefaultDatabaseClient.java:996) ~[spring-data-r2dbc-1.0.0.M1.jar:1.0.0.M1]
	at org.springframework.data.r2dbc.function.DefaultDatabaseClient$DefaultTypedInsertSpec.lambda$exchange$3(DefaultDatabaseClient.java:1002) ~[spring-data-r2dbc-1.0.0.M1.jar:1.0.0.M1]
	at org.springframework.data.r2dbc.function.DefaultSqlResult$2.apply(DefaultSqlResult.java:81) ~[spring-data-r2dbc-1.0.0.M1.jar:1.0.0.M1]
	at org.springframework.data.r2dbc.function.DefaultSqlResult$2.apply(DefaultSqlResult.java:78) ~[spring-data-r2dbc-1.0.0.M1.jar:1.0.0.M1]
	at org.springframework.data.r2dbc.function.DefaultDatabaseClient.doInConnectionMany(DefaultDatabaseClient.java:1018) ~[spring-data-r2dbc-1.0.0.M1.jar:1.0.0.M1]
	at org.springframework.data.r2dbc.function.DefaultDatabaseClient.lambda$inConnectionMany$2(DefaultDatabaseClient.java:159) ~[spring-data-r2dbc-1.0.0.M1.jar:1.0.0.M1]

There is no EnumCodec yet, but once implemented it should look like the one from postgresql: https://github.com/r2dbc/r2dbc-postgresql/blob/master/src/main/java/io/r2dbc/postgresql/codec/EnumCodec.java

Interestingly decoding of varchar to an enum value works. It is decoded to a String and Springs ConversionService turns it into an enum value.

I would have added a codec by myself, but there is no easy way to add a custom codec to DefaultCodecs.

Introduce direct/cursored preference Predicate to prefer direct/cursored execution

SQL Server statements can be executed using various execution methods:

  • SQLBATCH: Direct execution without parameters
  • SP_CURSOROPEN: Cursored execution with parameters
  • SP_EXECUTESQL: Direct execution with parameters
  • SP_CURSORPREPEXEC: Prepared execution with parameters

We should introduce a Predicate<String> (or a similar type) and a preference flag whether to prefer direct (cursor-less) or cursored execution. The predicate would allow controlling the preference regarding cursored/non-cursored execution.

Cursored execution has a factor 4 overhead in contrast to direct execution:

  • Direct execution: ~ 2000 queries/sec (simple queries, just SELECT foo FROM bar)
  • Cursored execution ~ 500 queries/sec (simple queries, just SELECT foo FROM bar)

SELECT TOP @size fails with R2dbcException

Parameter binding is not working at all on the latest snapshot or 1.0.0.M7.

Depending on what you do it says

Binding parameters is not supported for the statement [SELECT TOP $1 * FROM metadata
Binding parameters is not supported for the statement [SELECT TOP :size * FROM metadata
executeMany; uncategorized R2dbcException for SQL [SELECT TOP @size * FROM metadata]; Incorrect syntax near '@size'.; nested exception is R2dbcException{errorCode=102, sqlState='S0001'} io.r2dbc.mssql.MssqlException: Incorrect syntax near '@size'.

A prepared statement is recognized when it contains an @ but parameters which such a character cannot be bound. The documentation says named parameters start with : and indexed with $.

Defer error signal emission in MssqlResult until done token is processed

Error signals in MssqlResult are emitted directly and this causes cancellation of the upstream subscription. Frames may remain on the upstream source and this breaks downstream/next consumers.

We should defer error emission until receiving a done token and emit the error signal if an error was recorded.

Consider large chunks in StreamDecoder

StreamDecoder attempts to de-chunk a single segment and does not consider multiple chunks/header sequences in its aggregated body. This leaves not decoded segments in the aggregator buffer and protocol sequence does not advance.

This is a blocker for chunks greater 16k.

Related to #58.

Document supported data types

Hi, this is a first-timers-only issue. This means we've worked to make it more legible to folks who either haven't contributed to our codebase before or even folks who haven't contributed to open source before.

If that's you, we're interested in helping you take the first step and can answer questions and help you out as you do. Note that we're especially interested in contributions from people from groups underrepresented in free and open source software!

If you have contributed before, consider leaving this one for someone new, and looking through our general ideal-for-contribution issues. Thanks!

Background

We should document which SQL Server data types are currently supported by this driver to document features/limitations. Any non-documented data type is not supported.

Problem

Right now, it's not obvious which data types can be used and to which Java types SQL Server types map to.

Solution

Supported data types can be found by checking for Codec implementations in the io.r2dbc.mssql.codec package. Supported data types can be a table (matrix) between the SQL Server data type (e.g. VARCHAR) and to which Java type it maps to (e.g. java.lang.String, based on StringCodec.

The table with the type mapping should be added to our README.md.

Steps to fix

  • Claim this issue with a comment below and ask any clarifying questions you need.
  • Set up a repository locally following the Contributing Guidelines.
  • Try to fix the issue following the steps above.
  • Commit your changes and start a pull request.

Deliverables

  • Updated README.md containing a section which SQL Server data types are currently supported by this driver.

Support for XML data types

Ideally, we interchange SQLXML as Clob type. We should also provide a utility to retrieve SQLXML for document parsing and to provide Clob data from a Document.

Support SQL Server-specific transaction isolation levels by adding setTransactionIsolationLevel(MssqlIsolationLevel) to MssqlConnection

Hi, this is a first-timers-only issue. This means we've worked to make it more legible to folks who either haven't contributed to our codebase before or even folks who haven't contributed to open source before.

If that's you, we're interested in helping you take the first step and can answer questions and help you out as you do. Note that we're especially interested in contributions from people from groups underrepresented in free and open source software!

If you have contributed before, consider leaving this one for someone new, and looking through our general ideal-for-contribution issues. Thanks!

Background

SQL server supports more isolation levels than specified in R2DBC SPI.

Problem

We would like to support SNAPSHOT isolation in this driver. R2DBC defines isolation levels in an enum which makes extension impossible.

R2DBC SPI declares the following levels:

  • READ_COMMITTED
  • READ_UNCOMMITTED
  • REPEATABLE_READ
  • SERIALIZABLE

SQL Server supports additionally the SNAPSHOT level.

Solution

We need a driver-specific enum that contains all SQL server isolation levels (modelled along the lines of R2DBC's IsolationLevel enum).
We also need another setTransactionIsolationLevel method that allows to set the isolation level through the new enumeration.

Steps to fix

  • Claim this issue with a comment below and ask any clarifying questions you need.
  • Set up a repository locally following the Contributing Guidelines.
  • Try to fix the issue following the steps above.
  • Commit your changes and start a pull request.

Deliverables

  • Create a MssqlIsolationLevel enum.
  • Extend io.r2dbc.mssql.MssqlConnection by adding a setTransactionIsolationLevel(MssqlIsolationLevel) method.
  • Add a unit test for the new method to MssqlConnectionUnitTests.

Output of generated keys not working for UUID / uniqueidentifier

I am using UUID / uniqueidentifier primary keys.

CREATE TABLE test (
  id UNIQUEIDENTIFIER DEFAULT NEWID(),
  text VARCHAR(255)
)

When inserting a new object, I dont get the generated id. GENERATED_KEYS is empty.

INSERT INTO test (text) VALUES('test') select SCOPE_IDENTITY() AS GENERATED_KEYS;

Will return NULL.

That is an issue of SQL Server but the workaround would be to use the OUTPUT syntax:

INSERT INTO test (text) OUTPUT inserted.id VALUES('test');

That will actually return something like | id | B5BA707B-872E-4BFC-8A96-97A1D789E74C |

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.