r2dbc / r2dbc-mssql

R2DBC Driver for Microsoft SQL Server using TDS (Tabular Data Stream) Protocol
Apache License 2.0
183 stars 32 forks source link

`BigDecimal` with negative scale incorrectly encoded #228

Closed rjbgaspar closed 2 years ago

rjbgaspar commented 2 years ago

Bug Report

Versions

Current Behavior

Stack trace ``` 2021-10-30 08:39:38.976 ERROR 47496 --- [actor-tcp-nio-2] o.z.problem.spring.common.AdviceTraits : Internal Server Error org.springframework.r2dbc.UncategorizedR2dbcException: executeMany; SQL [INSERT INTO imos_organizer_process_parts (order_id, order_name, article_id, article_name, part_id, cam_cnc_file_path, multi_job_line, created_at, part_name, length, width, thickness, color, quantity, over_quantity, grain, part_code, part_description, typologie, part, id_mag, indice_prg, indice_opt, otimize, priority, all_1, aff_1, exit_work_center, compose, scarico_ruotato, stack_height, veneer, edge_1, edge_2, edge_3, edge_4, sovra_mat_x, sovra_mat_y, future_use_1, future_use_2, future_use_3, future_use_4, note, number_of_text_fields, text_field_1, text_field_2, text_field_3, text_field_4, text_field_5, text_field_6, text_field_7, text_field_8, text_field_9, text_field_10, text_field_11, text_field_12, text_field_13, text_field_14, text_field_15, text_field_16, article_position, imos_organizer_process_id, imos_organizer_process_order_id) VALUES (@P0_orderid, @P1_ordername, @P2_articleid, @P3_articlename, @P4_partid, @P5_camcncfilepath, @P6_multijobline, @P7_createdat, @P8_partname, @P9_length, @P10_width, @P11_thickness, @P12_color, @P13_quantity, @P14_overquantity, @P15_grain, @P16_partcode, @P17_partdescription, @P18_typologie, @P19_part, @P20_idmag, @P21_indiceprg, @P22_indiceopt, @P23_otimize, @P24_priority, @P25_all1, @P26_aff1, @P27_exitworkcenter, @P28_compose, @P29_scaricoruotato, @P30_stackheight, @P31_veneer, @P32_edge1, @P33_edge2, @P34_edge3, @P35_edge4, @P36_sovramatx, @P37_sovramaty, @P38_futureuse1, @P39_futureuse2, @P40_futureuse3, @P41_futureuse4, @P42_note, @P43_numberoftextfields, @P44_textfield1, @P45_textfield2, @P46_textfield3, @P47_textfield4, @P48_textfield5, @P49_textfield6, @P50_textfield7, @P51_textfield8, @P52_textfield9, @P53_textfield10, @P54_textfield11, @P55_textfield12, @P56_textfield13, @P57_textfield14, @P58_textfield15, @P59_textfield16, @P60_articleposition, @P61_imosorganizerprocessid, @P62_imosorganizerprocessorderid)]; The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 12 ("@P9_length"): Data type 0x6A has an invalid precision or scale.; nested exception is io.r2dbc.mssql.ExceptionFactory$MssqlNonTransientException: [8017] [S0003] The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 12 ("@P9_length"): Data type 0x6A has an invalid precision or scale. at org.springframework.r2dbc.connection.ConnectionFactoryUtils.convertR2dbcException(ConnectionFactoryUtils.java:238) Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: Error has been observed at the following site(s): |_ checkpoint ⇢ Handler com.gv.panther.web.rest.ImosOrganizerProcessPartResource#createImosOrganizerProcessPart(ImosOrganizerProcessPart) [DispatcherHandler] Stack trace: at org.springframework.r2dbc.connection.ConnectionFactoryUtils.convertR2dbcException(ConnectionFactoryUtils.java:238) at org.springframework.r2dbc.core.DefaultDatabaseClient.lambda$inConnectionMany$8(DefaultDatabaseClient.java:147) at reactor.core.publisher.Flux.lambda$onErrorMap$29(Flux.java:6720) at reactor.core.publisher.Flux.lambda$onErrorResume$30(Flux.java:6773) at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:94) at reactor.core.publisher.FluxUsingWhen$UsingWhenSubscriber.deferredError(FluxUsingWhen.java:411) at reactor.core.publisher.FluxUsingWhen$RollbackInner.onComplete(FluxUsingWhen.java:488) at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onComplete(Operators.java:2057) at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:88) at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142) at reactor.core.publisher.FluxFilter$FilterSubscriber.onComplete(FluxFilter.java:166) at reactor.core.publisher.FluxFilter$FilterConditionalSubscriber.onComplete(FluxFilter.java:300) at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onComplete(FluxMap.java:269) at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2399) at reactor.core.publisher.FluxMap$MapConditionalSubscriber.request(FluxMap.java:289) at reactor.core.publisher.FluxFilter$FilterConditionalSubscriber.request(FluxFilter.java:321) at reactor.core.publisher.FluxFilter$FilterSubscriber.request(FluxFilter.java:186) at reactor.core.publisher.FluxMap$MapSubscriber.request(FluxMap.java:162) at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onSubscribe(MonoIgnoreElements.java:71) at reactor.core.publisher.FluxMap$MapSubscriber.onSubscribe(FluxMap.java:92) at reactor.core.publisher.FluxFilter$FilterSubscriber.onSubscribe(FluxFilter.java:85) at reactor.core.publisher.FluxFilter$FilterConditionalSubscriber.onSubscribe(FluxFilter.java:219) at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onSubscribe(FluxMap.java:192) at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54) at reactor.core.publisher.MonoDeferContextual.subscribe(MonoDeferContextual.java:55) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) at reactor.core.publisher.Mono.subscribe(Mono.java:4150) at reactor.core.publisher.FluxUsingWhen$UsingWhenSubscriber.onError(FluxUsingWhen.java:377) at reactor.core.publisher.FluxFlatMap$FlatMapMain.checkTerminated(FluxFlatMap.java:842) at reactor.core.publisher.FluxFlatMap$FlatMapMain.drainLoop(FluxFlatMap.java:608) at reactor.core.publisher.FluxFlatMap$FlatMapMain.drain(FluxFlatMap.java:588) at reactor.core.publisher.FluxFlatMap$FlatMapMain.innerError(FluxFlatMap.java:863) at reactor.core.publisher.FluxFlatMap$FlatMapInner.onError(FluxFlatMap.java:990) at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onError(FluxPeekFuseable.java:234) at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onComplete(FluxPeekFuseable.java:271) at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onComplete(FluxHandleFuseable.java:229) at reactor.core.publisher.FluxWindowPredicate$WindowFlux.checkTerminated(FluxWindowPredicate.java:765) at reactor.core.publisher.FluxWindowPredicate$WindowFlux.drainRegular(FluxWindowPredicate.java:659) at reactor.core.publisher.FluxWindowPredicate$WindowFlux.drain(FluxWindowPredicate.java:745) at reactor.core.publisher.FluxWindowPredicate$WindowFlux.onComplete(FluxWindowPredicate.java:811) at reactor.core.publisher.FluxWindowPredicate$WindowPredicateMain.onComplete(FluxWindowPredicate.java:304) at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onComplete(FluxHandleFuseable.java:229) at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onComplete(FluxContextWrite.java:126) at io.r2dbc.mssql.util.FluxDiscardOnCancel$FluxDiscardOnCancelSubscriber.onComplete(FluxDiscardOnCancel.java:104) at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:259) at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:259) at reactor.core.publisher.FluxFilter$FilterSubscriber.onComplete(FluxFilter.java:166) at reactor.core.publisher.FluxHandle$HandleConditionalSubscriber.onComplete(FluxHandle.java:423) at reactor.core.publisher.EmitterProcessor.checkTerminated(EmitterProcessor.java:554) at reactor.core.publisher.EmitterProcessor.drain(EmitterProcessor.java:415) at reactor.core.publisher.EmitterProcessor.tryEmitComplete(EmitterProcessor.java:234) at reactor.core.publisher.EmitterProcessor.onComplete(EmitterProcessor.java:225) at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:259) at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:259) at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:259) at reactor.core.publisher.FluxHandle$HandleSubscriber.onComplete(FluxHandle.java:212) at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:133) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:250) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199) at reactor.core.publisher.EmitterProcessor.drain(EmitterProcessor.java:491) at reactor.core.publisher.EmitterProcessor.tryEmitNext(EmitterProcessor.java:299) at reactor.core.publisher.InternalManySink.emitNext(InternalManySink.java:27) at reactor.core.publisher.EmitterProcessor.onNext(EmitterProcessor.java:265) at io.r2dbc.mssql.client.ReactorNettyClient$1.next(ReactorNettyClient.java:244) at io.r2dbc.mssql.client.ReactorNettyClient$1.next(ReactorNettyClient.java:204) at io.r2dbc.mssql.message.token.Tabular$TabularDecoder.decode(Tabular.java:424) at io.r2dbc.mssql.client.ConnectionState$4$1.decode(ConnectionState.java:206) at io.r2dbc.mssql.client.StreamDecoder.withState(StreamDecoder.java:137) at io.r2dbc.mssql.client.StreamDecoder.decode(StreamDecoder.java:109) at io.r2dbc.mssql.client.ReactorNettyClient.lambda$new$6(ReactorNettyClient.java:254) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:184) at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:280) at reactor.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:389) at reactor.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:401) at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:94) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93) at io.r2dbc.mssql.client.ssl.TdsSslHandler.channelRead(TdsSslHandler.java:380) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:834) Caused by: io.r2dbc.mssql.ExceptionFactory$MssqlNonTransientException: The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 12 ("@P9_length"): Data type 0x6A has an invalid precision or scale. at io.r2dbc.mssql.ExceptionFactory.createException(ExceptionFactory.java:152) at io.r2dbc.mssql.MssqlResult.lambda$map$2(MssqlResult.java:179) at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onNext(FluxHandleFuseable.java:169) at reactor.core.publisher.FluxWindowPredicate$WindowFlux.drainRegular(FluxWindowPredicate.java:667) at reactor.core.publisher.FluxWindowPredicate$WindowFlux.drain(FluxWindowPredicate.java:745) at reactor.core.publisher.FluxWindowPredicate$WindowFlux.onNext(FluxWindowPredicate.java:787) at reactor.core.publisher.FluxWindowPredicate$WindowPredicateMain.onNext(FluxWindowPredicate.java:265) at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onNext(FluxHandleFuseable.java:184) at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) at io.r2dbc.mssql.util.FluxDiscardOnCancel$FluxDiscardOnCancelSubscriber.onNext(FluxDiscardOnCancel.java:89) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199) at reactor.core.publisher.FluxFilter$FilterSubscriber.onNext(FluxFilter.java:113) at reactor.core.publisher.FluxHandle$HandleConditionalSubscriber.onNext(FluxHandle.java:326) at reactor.core.publisher.EmitterProcessor.drain(EmitterProcessor.java:491) at reactor.core.publisher.EmitterProcessor.tryEmitNext(EmitterProcessor.java:299) at reactor.core.publisher.InternalManySink.emitNext(InternalManySink.java:27) at reactor.core.publisher.EmitterProcessor.onNext(EmitterProcessor.java:265) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199) at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:118) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:250) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199) at reactor.core.publisher.EmitterProcessor.drain(EmitterProcessor.java:491) at reactor.core.publisher.EmitterProcessor.tryEmitNext(EmitterProcessor.java:299) at reactor.core.publisher.InternalManySink.emitNext(InternalManySink.java:27) at reactor.core.publisher.EmitterProcessor.onNext(EmitterProcessor.java:265) at io.r2dbc.mssql.client.ReactorNettyClient$1.next(ReactorNettyClient.java:244) at io.r2dbc.mssql.client.ReactorNettyClient$1.next(ReactorNettyClient.java:204) at io.r2dbc.mssql.message.token.Tabular$TabularDecoder.decode(Tabular.java:424) at io.r2dbc.mssql.client.ConnectionState$4$1.decode(ConnectionState.java:206) at io.r2dbc.mssql.client.StreamDecoder.withState(StreamDecoder.java:137) at io.r2dbc.mssql.client.StreamDecoder.decode(StreamDecoder.java:109) at io.r2dbc.mssql.client.ReactorNettyClient.lambda$new$6(ReactorNettyClient.java:254) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:184) at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:280) at reactor.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:389) at reactor.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:401) at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:94) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93) at io.r2dbc.mssql.client.ssl.TdsSslHandler.channelRead(TdsSslHandler.java:380) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:834) ```

Table schema

Input Code ```sql CREATE TABLE dbo.imos_organizer_process_parts ( id INT IDENTITY NOT NULL , imos_organizer_process_order_id INT NOT NULL , order_id INT NOT NULL , order_name NVARCHAR (30) NOT NULL , article_id INT NOT NULL , article_name NVARCHAR (80) NOT NULL , part_id NVARCHAR (12) NOT NULL , cam_cnc_file_path NVARCHAR (255) NULL , multi_job_line NVARCHAR (max) NULL , created_at DATETIME NULL , updated_at DATETIME NULL , part_name NVARCHAR (255) NULL , length DECIMAL (10, 3) NULL , width DECIMAL (10, 3) NULL , thickness DECIMAL (10, 3) NULL , color NVARCHAR (20) NULL , quantity INT NULL , over_quantity INT NULL , grain SMALLINT NULL , part_code NVARCHAR (20) NULL , part_description NVARCHAR (50) NULL , typologie NVARCHAR (50) NULL , part SMALLINT NULL , id_mag SMALLINT NULL , indice_prg SMALLINT NULL , indice_opt SMALLINT NULL , otimize SMALLINT NULL , priority INT NULL , all_1 SMALLINT NULL , aff_1 SMALLINT NULL , exit_work_center SMALLINT NULL , compose SMALLINT NULL , scarico_ruotato SMALLINT NULL , stack_height DECIMAL (10, 6) NULL , veneer SMALLINT NULL , edge_1 NVARCHAR (20) NULL , edge_2 NVARCHAR (20) NULL , edge_3 NVARCHAR (20) NULL , edge_4 NVARCHAR (20) NULL , sovra_mat_x DECIMAL (10, 6) NULL , sovra_mat_y DECIMAL (10, 6) NULL , future_use_1 INT NULL , future_use_2 INT NULL , future_use_3 DECIMAL (10, 6) NULL , future_use_4 DECIMAL (10, 6) NULL , note NVARCHAR (50) NULL , number_of_text_fields SMALLINT NULL , text_field_1 NVARCHAR (80) NULL , text_field_2 NVARCHAR (80) NULL , text_field_3 NVARCHAR (80) NULL , text_field_4 NVARCHAR (80) NULL , text_field_5 NVARCHAR (80) NULL , text_field_6 NVARCHAR (80) NULL , text_field_7 NVARCHAR (80) NULL , text_field_8 NVARCHAR (80) NULL , text_field_9 NVARCHAR (80) NULL , text_field_10 NVARCHAR (80) NULL , text_field_11 NVARCHAR (80) NULL , text_field_12 NVARCHAR (80) NULL , text_field_13 NVARCHAR (80) NULL , text_field_14 NVARCHAR (80) NULL , text_field_15 NVARCHAR (80) NULL , text_field_16 NVARCHAR (80) NULL , text_field_17 NVARCHAR (80) NULL , text_field_18 NVARCHAR (80) NULL , text_field_19 NVARCHAR (80) NULL , text_field_20 NVARCHAR (80) NULL , text_field_21 NVARCHAR (80) NULL , text_field_22 NVARCHAR (80) NULL , text_field_23 NVARCHAR (80) NULL , text_field_24 NVARCHAR (80) NULL , text_field_25 NVARCHAR (80) NULL , text_field_26 NVARCHAR (80) NULL , text_field_27 NVARCHAR (80) NULL , text_field_28 NVARCHAR (80) NULL , text_field_29 NVARCHAR (80) NULL , text_field_30 NVARCHAR (80) NULL , text_field_31 NVARCHAR (80) NULL , text_field_32 NVARCHAR (80) NULL , text_field_33 NVARCHAR (80) NULL , text_field_34 NVARCHAR (80) NULL , text_field_35 NVARCHAR (80) NULL , text_field_36 NVARCHAR (80) NULL , text_field_37 NVARCHAR (80) NULL , text_field_38 NVARCHAR (80) NULL , text_field_39 NVARCHAR (80) NULL , text_field_40 NVARCHAR (80) NULL , sort_key INT NULL , article_position NVARCHAR (30) NULL , original_quantity INT NULL , imos_organizer_process_id INT NULL , PRIMARY KEY (id) WITH (FILLFACTOR = 70) ) GO ```

Steps to reproduce

The domain object is set and the column with BigDecimal is set. Tthe value set is 9.5E+2 (Scientific E notation) which means 950.000, the insert is created.

Input Code ```java @Override public Mono insert(S entity) { return entityManager.insert(entity); } ```

Expected behavior/code

The object to be inserted

Possible Solution

  • Perform a conversion, before inserting the data.

  • A way to read the value in the annotation, before making the conversion:

    @org.springframework.data.relational.core.mapping.Column("length")
    @javax.persistence.Column(name="length", precision = 10, scale = 3)
    private BigDecimal length;

    Additional context

  • The same domain obejct and repository can perform the insert in my dev H2 database.

  • MS SQL server support scientific notation since I'm able to do this:

    UPDATE dbo.imos_organizer_process_parts
    SET length = 9.5E+2 
    WHERE id = 1
  • I have write a custom workaround to do as follow

    @WritingConverter
    public enum BigDecimalWriteConverter implements Converter<BigDecimal, BigDecimal> {
        INSTANCE;
    
        @Override
        public BigDecimal convert(BigDecimal source) {
            // Avoid scientific notation with BigDecimal
            return source != null ? new BigDecimal(source.stripTrailingZeros().toPlainString()) : null;
        }
    }
mp911de commented 2 years ago

This is a bug in the computation of the scale. new BigDecimal("9.5E+2").scale() returns -1 and we didn't cater for this case.