Closed lukaseder closed 3 years ago
Batches are run differently from non-batches. Simple batches without a fetch size use SqlBatch
while batches with a fetch size or parametrized statements (seems that @t
is being identified as parameter) are sent via the RPC interface leveraging cursors. The response structure between both is somewhat different and it seems that result processing has somewhere a bug to identify Result
bounds
Thanks for the insight. From a user perspective, they probably shouldn't be different, though? I recently ran into an issue with mssql-jdbc, where a local variable in statement 1 of a batch conflicted with a local variable of the same name in statement 2.
seems that
@t
is being identified as parameter
Ah yes! That would be a bug then! Is it the cause of this one, or a new one? In case of which I'd be happy to report another bug.
The problem with variable identification is somewhat that we can't know whether something is a variable because a lot of things in the SQL server universe start with @
(DECLARE @
, SELECT @@…
). I think that's a general bug in the RPC result handling. Feel free to create another ticket to align Batch vs. non-batch result behavior. We can use this one to fix the Result
behavior observed from Batch
.
Alright, the @
problem is here: https://github.com/r2dbc/r2dbc-mssql/issues/197
Confirming that Batch
works as expected while createStatement(…)
doesn't split up the Result
:
Batch
Request: SQLBatch [sql="DECLARE @t TABLE(i INT); INSERT INTO @t VALUES (1),(2),(3); SELECT * FROM @t;"]
// first Result
Response: DoneToken [done=false, hasCount=true, rowCount=3, hasMore=true, currentCommand=0]
// second Result
Response: ColumnMetadataToken [columns=[Column [name='i", type=MutableTypeInformation [maxLength=4, lengthStrategy=BYTELENTYPE, precision=10, displaySize=11, scale=0, flags=9, serverType=int, userType=0, udtTypeName="null", collation=null, charset=null], table=null]]]
Response: io.r2dbc.mssql.message.token.RowToken@1c741110
Response: io.r2dbc.mssql.message.token.RowToken@6701ff63
Response: io.r2dbc.mssql.message.token.RowToken@3d40a7c2
Response: DoneToken [done=true, hasCount=true, rowCount=3, hasMore=false, currentCommand=0]
createStatement(…).execute()
Request: RPCRequest [procName='null', procId=10, optionFlags=io.r2dbc.mssql.message.token.RpcRequest$OptionFlags@1136b469, statusFlags=0, parameterDescriptors=[RpcString [name='null', value=DECLARE @t TABLE(i INT);INSERT INTO @t VALUES (1),(2),(3);SELECT * FROM @t;], RpcString [name='null', value=]]]
// Single Result object
Response: DoneInProcToken [done=false, hasCount=true, rowCount=3, hasMore=true, currentCommand=0]
Response: ColumnMetadataToken [columns=[Column [name='i", type=MutableTypeInformation [maxLength=4, lengthStrategy=BYTELENTYPE, precision=10, displaySize=11, scale=0, flags=9, serverType=int, userType=0, udtTypeName="null", collation=null, charset=null], table=null]]]
Response: io.r2dbc.mssql.message.token.RowToken@742ddf3a
Response: io.r2dbc.mssql.message.token.RowToken@59c66b51
Response: io.r2dbc.mssql.message.token.RowToken@e7bd10e
Response: DoneInProcToken [done=false, hasCount=true, rowCount=3, hasMore=true, currentCommand=0]
Response: ReturnStatus [status=0]
Response: DoneProcToken [done=true, hasCount=false, rowCount=0, hasMore=false, currentCommand=0]
Bug Report
Versions
Current Behavior
This code:
Prints:
Expected behavior/code
I would expect the same behaviour as in JDBC. Here's a loop that collects both update counts and result sets:
Printing:
The JDBC version actually checks whether the current result is an update count or a result set (this isn't currently possible with R2DBC, see https://github.com/r2dbc/r2dbc-spi/issues/27). But even if we embed this knowledge into the reactive version, I'm not getting the right results:
This still prints the wrong thing
Possible Solution
As a workaround, it seems I can use a formal batch, not the statement batch syntax (though, behind the scenes, I would imagine these should be the same thing):
Producing: