Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error passing blobs to a stored procedure #209

Open
jeroen-vh opened this issue Feb 24, 2021 · 0 comments
Open

Error passing blobs to a stored procedure #209

jeroen-vh opened this issue Feb 24, 2021 · 0 comments

Comments

@jeroen-vh
Copy link

Hello, first of all, thanks for creating this great project. I've been experimenting with this new library and testing some code I use to execute stored procedures. I'm having trouble when passing an argument to the stored procedure containing more than 16384 characters or bytes.

Describe the bug
When passing an argument of the ASE type image or text to the stored procedure I get the following error from the ASE server when the argument contains a string or byte array larger than 16384 characters/bytes:

The token datastream length was not correct. This is an internal protocol error.

This works with the Sybase.AdoNet4.AseClient library version 4.157.1300.

To Reproduce
Create a stored procedure that accepts a text argument:

create or replace procedure [dbo].[sp_test_text_type]
  @input text,
  @output int output
as
begin
  set @output = len(@input)
end

C# code:

    using (var connection = new AseConnection(connectionString))
    {
        connection.Open();
        using (var command = connection.CreateCommand())
        {
            command.CommandText = "sp_test_text_type";
            command.CommandType = CommandType.StoredProcedure;

            var input = new string('a', 20000);

            var pIn = command.CreateParameter();
            pIn.ParameterName = "@input";
            pIn.Value = input;
            pIn.AseDbType = AseDbType.Text;
            command.Parameters.Add(pIn);

            var pOut = command.CreateParameter();
            pOut.ParameterName = "@output";
            pOut.Value = DBNull.Value;
            pOut.DbType = DbType.Int32;
            pOut.Direction = ParameterDirection.Output;
            command.Parameters.Add(pOut);

            command.ExecuteNonQuery();
        }
    }

Debug output:

InternalConnectionFactory.GetNewConnection start

----------  Send packet   ----------
Write TDS_BUF_LOGIN
Write TDS_CAPABILITY

---------- Receive Tokens ----------
TDS_ENVCHANGE: TDS_ENV_CHARSET - iso_1 -> iso_1
INFO  [10] [L:0]: Changed client character set setting to 'iso_1'.
TDS_ENVCHANGE: TDS_ENV_DB - master -> lisdb
INFO  [10] [L:0]: Changed database context to 'lisdb'.
TDS_ENVCHANGE: TDS_ENV_LANG -  -> us_english
INFO  [10] [L:0]: Changed language setting to 'us_english'.
TDS_ENVCHANGE: TDS_ENV_PACKSIZE -  -> 2048
<- TDS_LOGINACK: TDS 5.0.0.0, ASE 16.0.3
Login success
<- TDS_DONE: TDS_DONE_FINAL (263)

----------  Send packet   ----------
Write TDS_BUF_NORMAL
-> TDS_OPTIONCMD: TDS_OPT_SET, TDS_OPT_TEXTSIZE, 00 80 00 00
---------- Receive Tokens ----------
<- TDS_DONE: TDS_DONE_FINAL (263)
TDS_DONE: TDS_DONE_FINAL

========== ExecuteNonQuery==========
Transaction set: False

----------  Send packet   ----------
Write TDS_BUF_NORMAL
-> TDS_DBRPC: sp_test_text_type
-> TDS_PARAMFMT2: 2 parameters
  -> @input: TDS_BLOB (20000) (ut:0)
  -> @output: TDS_INTN (4) (ut:0)
-> TDS_PARAMS: 2 parameters

---------- Receive Tokens ----------
ERROR [16] [L:0]: The token datastream length was not correct. This is an internal protocol error.
<- TDS_DONE: TDS_DONE_ERROR (263)
TDS_DONE: TDS_DONE_ERROR
<- TDS_RETURNSTATUS: -6
<- TDS_DONE: TDS_DONE_FINAL (263)
TDS_DONE: TDS_DONE_FINAL

A solution to get the above sample working is changing pIn.AseDbType = AseDbType.Text;
to: pIn.DbType = DbType.String;

This results in 40000 bytes sent to the server with UserType 36:

-> TDS_PARAMFMT2: 2 parameters
  -> @input: TDS_BLOB (40000) (ut:36)
  -> @output: TDS_INTN (4) (ut:0)

and no error. I'm unable to create a similar solution for the image type.

Expected behavior
Using the old Sybase .Net Framework library this results in the output argument returning 20000.

Environment

  • Tested in both .Net Framework 4.8 and .Net Core 3.1
  • AdoNetCore.AseClient nuget package version 0.19.2
  • SAP ASE: Adaptive Server Enterprise/16.0 SP03 PL08/EBF 28921
  • SAP ASE Default Character Set: iso_1

Additional context
If wanted, I can also provide a sample for the image type bug using a byte array.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant