question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Unable to process TVP when 1st row contains null on varchar

See original GitHub issue

Hello,

We are running the code below in Python (3.8) using pytds version 1.11.0 and I am receiving the error message “pytds.tds_base.OperationalError: The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Table-valued parameter 5 (""), row 2, column 6: Data type 0xE7 has an invalid data length or metadata length.

Looking at the error it seems that colums 6 in row 2 is exceeding the data type size, however, if I revers the order of the rows, this code runs successfully.

It looks like the None value provided on the first row is causing the issue, since replacing this None by an empty string is making the code to run without any problem.

I have also tried to use callproc method instead of execute, but it is returnining the same error.

The expected behaviour is to accept the None value and proceed with the others rows without any problem since all of them are complient with the type definition.

Supporting code:

CREATE TYPE MySchema.MyUserStoredProcedureDataType AS TABLE(
	[Column_001] [varchar](500) NULL,
	[Column_002] [varchar](500) NOT NULL,
	[Column_003] [varchar](500) NULL,
	[Column_004] [varchar](500) NOT NULL,
	[Column_005] [tinyint] NOT NULL,
	[Column_006] [varchar](500) NULL,
	[Column_007] [datetime2](2) NOT NULL
)

import pytds
import datetime

sql_statement = """EXEC MySchema.MyUserStoredProcedure
                            @Data = %(tvp)s,
                            @EventUUID = %(event_uuid)s,
                            @UserUUID = %(user_uuid)s;"""


array_tvp = [
      ['d191affd66e4d8ef1cd14a368cc3b920', 'SOME TEXT ROW 1 COLUMN 2', 'SOME TEXT ROW 1 COLUMN 3', 'SOME TEXT ROW 1 COLUMN 4', 100, None, datetime.datetime(2021, 5, 7, 21, 32, 45)]
    , ['7b61f7245e1f5bf0d17f0d14ad57339d', 'SOME TEXT ROW 2 COLUMN 2', 'SOME TEXT ROW 2 COLUMN 3', 'SOME TEXT ROW 2 COLUMN 4', 1, 'd191affd66e4d8ef1cd14a368cc3b920', datetime.datetime(2021, 5, 7, 21, 32, 45)]
]
with conn.cursor() as cursor:

    logger.info('Execute SQL statement for MySchema.MyUserStoredProcedure')
    cursor.execute(
        operation=sql_statement,
        params={
            "tvp": pytds.TableValuedParam(
                type_name='MySchema.MyUserStoredProcedureDataType',
                rows=array_tvp
            ),
            "event_uuid": '2ca5a8df-27de-4fc9-b8bd-314f64af420c',
            "user_uuid": '29c1da9b-661d-4bc8-a24a-c4f60155b8fd'
        }
    )
    cursor.get_proc_return_status()

    logger.info('Execute SQL statement for MySchema.MyUserStoredProcedure successfully executed')


Thanks in advance for your help!

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
takoaucommented, Dec 19, 2022

@baresh561 @jdiaz-merkle made 2 helper functions to find out user data types and populate a list of Column objects:

def getType(tvtName, cursor):
    from pytds.tds_base import Column
    parser = pytds.tds_types.DeclarationsParser()
    rs = cursor.execute("SELECT name, system_type_name, is_nullable FROM sys.dm_exec_describe_first_result_set('SELECT * FROM @test', N'@test " + tvtName + " READONLY', 0) ORDER BY column_ordinal").fetchall()
    return [Column(name=row[0], type=parser.parse(row[1]), flags = row[2] & Column.fNullable) for row in rs]

array_tvp = [
    [None, 'SOME TEXT ROW 1 COLUMN 2', 'SOME TEXT ROW 1 COLUMN 3', 'SOME TEXT ROW 1 COLUMN 4', 100, '1', datetime.datetime(2021, 5, 7, 21, 32, 45)]
    , ['7b61f7245e1f5bf0d17f0d14ad57339d', 'SOME TEXT ROW 2 COLUMN 2', 'SOME TEXT ROW 2 COLUMN 3', 'SOME TEXT ROW 2 COLUMN 4', 1, 'd191affd66e4d8ef1cd14a368cc3b920', datetime.datetime(2021, 5, 7, 21, 32, 45)]
]

#  getType() to get column list from user-defined types and getTable() for tables
with conn.cursor() as cursor:
    columns = getType("testType", cursor)
with conn.cursor() as cursor:
    cursor.execute(
        operation=sql_statement,
        params={
            "tvp": pytds.TableValuedParam(
                type_name='testType',
                columns=columns,
                rows=array_tvp)
        }
    )
0reactions
takoaucommented, Dec 19, 2022

@baresh561 @jdiaz-merkle Knowing it has been late for years. pytds estimates column type by checking first row of data. Column type default to be nvarchar(1) If data in first column is None. Hence error is thrown if data succeeding is not nvarchar(1).

Read more comments on GitHub >

github_iconTop Results From Across the Web

tedious TVP, is a becoming blocking operation for large data
I am trying to do a call a stored procedure with a TVP as a parameter . This TVP is built from a...
Read more >
c# - Table-valued parameter insert performing poorly
A table variable (which a table-valued-parameter essentially is) is always assumed by SQL Server to contain exactly 1 row (even if it ...
Read more >
Scope_Identity() returns null after inserting first row in table
The issue is when isFirstMSH is false, the ProcessID value is NULL. If isFirstMSH value is false, it should insert the last generated...
Read more >
Can table-valued parameter be null? - SQLServerCentral
Most parameters to a SP are required unless a default value is set with = in the parameters list. In the case of...
Read more >
Column, parameter, or variable #1: Cannot find data type ...
I had hard time to try insert into database, I am using pyodbc for tk interface. This what I have created in MSSMS...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found