Skip to content

CHORE: e2e bulk copy into a CLR UDT column (GH-667)#683

Open
gargsaumya wants to merge 1 commit into
mainfrom
saumya/gh667-bulkcopy-udt-e2e
Open

CHORE: e2e bulk copy into a CLR UDT column (GH-667)#683
gargsaumya wants to merge 1 commit into
mainfrom
saumya/gh667-bulkcopy-udt-e2e

test: e2e bulk copy into a CLR UDT column (GH-667)

f389d0c
Select commit
Loading
Failed to load commit list.
Azure Pipelines / MSSQL-Python-PR-Validation failed Jul 16, 2026 in 45m 26s

Build #pr-validation-pipeline had test failures

Details

Tests

  • Failed: 16 (0.05%)
  • Passed: 30,119 (96.88%)
  • Other: 953 (3.07%)
  • Total: 31,088

Annotations

Check failure on line 2694 in Build log

See this annotation in the file changed.

@azure-pipelines azure-pipelines / MSSQL-Python-PR-Validation

Build log #L2694

Bash exited with code '1'.

Check failure on line 2736 in Build log

See this annotation in the file changed.

@azure-pipelines azure-pipelines / MSSQL-Python-PR-Validation

Build log #L2736

Bash exited with code '1'.

Check failure on line 10 in Build log

See this annotation in the file changed.

@azure-pipelines azure-pipelines / MSSQL-Python-PR-Validation

Build log #L10

No code coverage results were found to publish.

Check failure on line 2694 in Build log

See this annotation in the file changed.

@azure-pipelines azure-pipelines / MSSQL-Python-PR-Validation

Build log #L2694

Bash exited with code '1'.

Check failure on line 1 in test_bulkcopy_udt_geometry

See this annotation in the file changed.

@azure-pipelines azure-pipelines / MSSQL-Python-PR-Validation

test_bulkcopy_udt_geometry

RuntimeError: Sql Error: 102: Class 15: State 1: Incorrect syntax near ')'. on 845b009edde8 in  at line 1
Raw output
cursor = <mssql_python.cursor.Cursor object at 0x7fb7f50bb6b0>

    def test_bulkcopy_udt_geometry(cursor):
        """GH-667: bulk copy into a CLR UDT column.
    
        Custom (user-defined) CLR UDTs require a deployed assembly, so this test uses
        the built-in ``geometry`` CLR UDT, which travels the identical TDS ``0xF0``
        wire path. Before the fix, bulk copy of any UDT column failed with
        ``Unsupported TDS type for bulk copy: 0xF0``; the fix streams UDTs as
        ``varbinary(max)`` (their ``IBinarySerialize`` form).
    
        The test seeds a ``geometry`` column, reads the serialized UDT bytes back,
        bulk copies them into a second ``geometry`` column, and verifies a byte-exact
        round-trip (including a NULL).
        """
        src = "mssql_python_bcp_udt_src"
        dst = "mssql_python_bcp_udt_dst"
    
        def _read(table):
            cursor.execute(f"SELECT id, g FROM {table} ORDER BY id")
            return [(r[0], bytes(r[1]) if r[1] is not None else None) for r in cursor.fetchall()]
    
        try:
            # Seed a geometry (built-in CLR UDT) source table via T-SQL.
            cursor.execute(f"IF OBJECT_ID('{src}', 'U') IS NOT NULL DROP TABLE {src}")
            cursor.execute(f"CREATE TABLE {src} (id INT NOT NULL, g geometry NULL)")
            cursor.execute(
                f"INSERT INTO {src} (id, g) VALUES "
                "(1, geometry::STGeomFromText('POINT(1 2)', 0)), "
                "(2, geometry::STGeomFromText('LINESTRING(0 0, 10 10, 20 25)', 0)), "
                "(3, NULL), "
                "(4, geometry::STGeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))', 0))"
            )
            cursor.connection.commit()
    
            # Read the serialized UDT bytes back (unaffected by the fix).
            source_rows = _read(src)
            assert len(source_rows) == 4
            assert sum(1 for _, g in source_rows if g is not None) == 3
            assert any(g is None for _, g in source_rows)
    
            # Destination geometry table.
            cursor.execute(f"IF OBJECT_ID('{dst}', 'U') IS NOT NULL DROP TABLE {dst}")
            cursor.execute(f"CREATE TABLE {dst} (id INT NOT NULL, g geometry NULL)")
            cursor.connection.commit()
    
            # Bulk copy the UDT bytes into the geometry column. Requires the GH-667
            # fix in the bundled mssql_py_core (both the varbinary(max) wire mapping
            # and the bytes->UDT value-coercion). Pre-fix this failed with
            # "Unsupported TDS type for bulk copy: 0xF0" / a bad varbinary(-1) type /
            # a "target SQL type is Udt" coercion error.
>           result = cursor.bulkcopy(dst, source_rows, timeout=60)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/test_019_bulkcopy.py:508: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <mssql_python.cursor.Cursor object at 0x7fb7f50bb6b0>
table_name = 'mssql_python_bcp_udt_dst'
data = [(1, b'\x00\x00\x00\x00\x01\x0c\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@'), (2, b'\x00\x00\x00\x00\x0...\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x01\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x03')]
batch_size = 0, timeout = 60, column_mappings = None, keep_identity = False
check_constraints = False, table_lock = False, keep_nulls = False
fire_triggers = False, use_internal_transaction = False

    def bulkcopy(
        self,
        table_name: str,
        data: Iterable[Union[Tuple, "Row"]],
        batch_size: int = 0,
        timeout: int = 30,
        column_mappings: Optional[Union[List[str], List[Tuple[int, str]]]] = None,
        keep_identity: bool = False,
        check_constraints: bool = False,
        table_lock: bool = False,
        keep_null
... [The stack trace has been truncated as it exceeded the maximum allowed size. Please refer to the complete log available in the Test Run attachments for full details.]

Check failure on line 1 in test_bulkcopy_udt_geometry

See this annotation in the file changed.

@azure-pipelines azure-pipelines / MSSQL-Python-PR-Validation

test_bulkcopy_udt_geometry

RuntimeError: Sql Error: 102: Class 15: State 1: Incorrect syntax near ')'. on runnervm0ifvb\LOCALDB#87192DB3 in  at line 1
Raw output
cursor = <mssql_python.cursor.Cursor object at 0x000002C95CE21D00>

    def test_bulkcopy_udt_geometry(cursor):
        """GH-667: bulk copy into a CLR UDT column.
    
        Custom (user-defined) CLR UDTs require a deployed assembly, so this test uses
        the built-in ``geometry`` CLR UDT, which travels the identical TDS ``0xF0``
        wire path. Before the fix, bulk copy of any UDT column failed with
        ``Unsupported TDS type for bulk copy: 0xF0``; the fix streams UDTs as
        ``varbinary(max)`` (their ``IBinarySerialize`` form).
    
        The test seeds a ``geometry`` column, reads the serialized UDT bytes back,
        bulk copies them into a second ``geometry`` column, and verifies a byte-exact
        round-trip (including a NULL).
        """
        src = "mssql_python_bcp_udt_src"
        dst = "mssql_python_bcp_udt_dst"
    
        def _read(table):
            cursor.execute(f"SELECT id, g FROM {table} ORDER BY id")
            return [(r[0], bytes(r[1]) if r[1] is not None else None) for r in cursor.fetchall()]
    
        try:
            # Seed a geometry (built-in CLR UDT) source table via T-SQL.
            cursor.execute(f"IF OBJECT_ID('{src}', 'U') IS NOT NULL DROP TABLE {src}")
            cursor.execute(f"CREATE TABLE {src} (id INT NOT NULL, g geometry NULL)")
            cursor.execute(
                f"INSERT INTO {src} (id, g) VALUES "
                "(1, geometry::STGeomFromText('POINT(1 2)', 0)), "
                "(2, geometry::STGeomFromText('LINESTRING(0 0, 10 10, 20 25)', 0)), "
                "(3, NULL), "
                "(4, geometry::STGeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))', 0))"
            )
            cursor.connection.commit()
    
            # Read the serialized UDT bytes back (unaffected by the fix).
            source_rows = _read(src)
            assert len(source_rows) == 4
            assert sum(1 for _, g in source_rows if g is not None) == 3
            assert any(g is None for _, g in source_rows)
    
            # Destination geometry table.
            cursor.execute(f"IF OBJECT_ID('{dst}', 'U') IS NOT NULL DROP TABLE {dst}")
            cursor.execute(f"CREATE TABLE {dst} (id INT NOT NULL, g geometry NULL)")
            cursor.connection.commit()
    
            # Bulk copy the UDT bytes into the geometry column. Requires the GH-667
            # fix in the bundled mssql_py_core (both the varbinary(max) wire mapping
            # and the bytes->UDT value-coercion). Pre-fix this failed with
            # "Unsupported TDS type for bulk copy: 0xF0" / a bad varbinary(-1) type /
            # a "target SQL type is Udt" coercion error.
>           result = cursor.bulkcopy(dst, source_rows, timeout=60)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests\test_019_bulkcopy.py:508: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <mssql_python.cursor.Cursor object at 0x000002C95CE21D00>
table_name = 'mssql_python_bcp_udt_dst'
data = [(1, b'\x00\x00\x00\x00\x01\x0c\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@'), (2, b'\x00\x00\x00\x00\x0...\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x01\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x03')]
batch_size = 0, timeout = 60, column_mappings = None, keep_identity = False
check_constraints = False, table_lock = False, keep_nulls = False
fire_triggers = False, use_internal_transaction = False

    def bulkcopy(
        self,
        table_name: str,
        data: Iterable[Union[Tuple, "Row"]],
        batch_size: int = 0,
        timeout: int = 30,
        column_mappings: Optional[Union[List[str], List[Tuple[int, str]]]] = None,
        keep_identity: bool = False,
        check_constraints: bool = False,
        table_lock: bool = False,
        ke
... [The stack trace has been truncated as it exceeded the maximum allowed size. Please refer to the complete log available in the Test Run attachments for full details.]

Check failure on line 1 in test_bulkcopy_udt_geometry

See this annotation in the file changed.

@azure-pipelines azure-pipelines / MSSQL-Python-PR-Validation

test_bulkcopy_udt_geometry

RuntimeError: Sql Error: 102: Class 15: State 1: Incorrect syntax near ')'. on 60b1f0771cc0 in  at line 1
Raw output
cursor = <mssql_python.cursor.Cursor object at 0x7f2a74401ae0>

    def test_bulkcopy_udt_geometry(cursor):
        """GH-667: bulk copy into a CLR UDT column.
    
        Custom (user-defined) CLR UDTs require a deployed assembly, so this test uses
        the built-in ``geometry`` CLR UDT, which travels the identical TDS ``0xF0``
        wire path. Before the fix, bulk copy of any UDT column failed with
        ``Unsupported TDS type for bulk copy: 0xF0``; the fix streams UDTs as
        ``varbinary(max)`` (their ``IBinarySerialize`` form).
    
        The test seeds a ``geometry`` column, reads the serialized UDT bytes back,
        bulk copies them into a second ``geometry`` column, and verifies a byte-exact
        round-trip (including a NULL).
        """
        src = "mssql_python_bcp_udt_src"
        dst = "mssql_python_bcp_udt_dst"
    
        def _read(table):
            cursor.execute(f"SELECT id, g FROM {table} ORDER BY id")
            return [(r[0], bytes(r[1]) if r[1] is not None else None) for r in cursor.fetchall()]
    
        try:
            # Seed a geometry (built-in CLR UDT) source table via T-SQL.
            cursor.execute(f"IF OBJECT_ID('{src}', 'U') IS NOT NULL DROP TABLE {src}")
            cursor.execute(f"CREATE TABLE {src} (id INT NOT NULL, g geometry NULL)")
            cursor.execute(
                f"INSERT INTO {src} (id, g) VALUES "
                "(1, geometry::STGeomFromText('POINT(1 2)', 0)), "
                "(2, geometry::STGeomFromText('LINESTRING(0 0, 10 10, 20 25)', 0)), "
                "(3, NULL), "
                "(4, geometry::STGeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))', 0))"
            )
            cursor.connection.commit()
    
            # Read the serialized UDT bytes back (unaffected by the fix).
            source_rows = _read(src)
            assert len(source_rows) == 4
            assert sum(1 for _, g in source_rows if g is not None) == 3
            assert any(g is None for _, g in source_rows)
    
            # Destination geometry table.
            cursor.execute(f"IF OBJECT_ID('{dst}', 'U') IS NOT NULL DROP TABLE {dst}")
            cursor.execute(f"CREATE TABLE {dst} (id INT NOT NULL, g geometry NULL)")
            cursor.connection.commit()
    
            # Bulk copy the UDT bytes into the geometry column. Requires the GH-667
            # fix in the bundled mssql_py_core (both the varbinary(max) wire mapping
            # and the bytes->UDT value-coercion). Pre-fix this failed with
            # "Unsupported TDS type for bulk copy: 0xF0" / a bad varbinary(-1) type /
            # a "target SQL type is Udt" coercion error.
>           result = cursor.bulkcopy(dst, source_rows, timeout=60)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/test_019_bulkcopy.py:508: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <mssql_python.cursor.Cursor object at 0x7f2a74401ae0>
table_name = 'mssql_python_bcp_udt_dst'
data = [(1, b'\x00\x00\x00\x00\x01\x0c\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@'), (2, b'\x00\x00\x00\x00\x0...\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x01\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x03')]
batch_size = 0, timeout = 60, column_mappings = None, keep_identity = False
check_constraints = False, table_lock = False, keep_nulls = False
fire_triggers = False, use_internal_transaction = False

    def bulkcopy(
        self,
        table_name: str,
        data: Iterable[Union[Tuple, "Row"]],
        batch_size: int = 0,
        timeout: int = 30,
        column_mappings: Optional[Union[List[str], List[Tuple[int, str]]]] = None,
        keep_identity: bool = False,
        check_constraints: bool = False,
        table_lock: bool = False,
        keep_null
... [The stack trace has been truncated as it exceeded the maximum allowed size. Please refer to the complete log available in the Test Run attachments for full details.]

Check failure on line 1 in test_bulkcopy_udt_geometry

See this annotation in the file changed.

@azure-pipelines azure-pipelines / MSSQL-Python-PR-Validation

test_bulkcopy_udt_geometry

RuntimeError: Sql Error: 102: Class 15: State 1: Incorrect syntax near ')'. on 1f3cc51c879b in  at line 1
Raw output
cursor = <mssql_python.cursor.Cursor object at 0x111d4bce0>

    def test_bulkcopy_udt_geometry(cursor):
        """GH-667: bulk copy into a CLR UDT column.
    
        Custom (user-defined) CLR UDTs require a deployed assembly, so this test uses
        the built-in ``geometry`` CLR UDT, which travels the identical TDS ``0xF0``
        wire path. Before the fix, bulk copy of any UDT column failed with
        ``Unsupported TDS type for bulk copy: 0xF0``; the fix streams UDTs as
        ``varbinary(max)`` (their ``IBinarySerialize`` form).
    
        The test seeds a ``geometry`` column, reads the serialized UDT bytes back,
        bulk copies them into a second ``geometry`` column, and verifies a byte-exact
        round-trip (including a NULL).
        """
        src = "mssql_python_bcp_udt_src"
        dst = "mssql_python_bcp_udt_dst"
    
        def _read(table):
            cursor.execute(f"SELECT id, g FROM {table} ORDER BY id")
            return [(r[0], bytes(r[1]) if r[1] is not None else None) for r in cursor.fetchall()]
    
        try:
            # Seed a geometry (built-in CLR UDT) source table via T-SQL.
            cursor.execute(f"IF OBJECT_ID('{src}', 'U') IS NOT NULL DROP TABLE {src}")
            cursor.execute(f"CREATE TABLE {src} (id INT NOT NULL, g geometry NULL)")
            cursor.execute(
                f"INSERT INTO {src} (id, g) VALUES "
                "(1, geometry::STGeomFromText('POINT(1 2)', 0)), "
                "(2, geometry::STGeomFromText('LINESTRING(0 0, 10 10, 20 25)', 0)), "
                "(3, NULL), "
                "(4, geometry::STGeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))', 0))"
            )
            cursor.connection.commit()
    
            # Read the serialized UDT bytes back (unaffected by the fix).
            source_rows = _read(src)
            assert len(source_rows) == 4
            assert sum(1 for _, g in source_rows if g is not None) == 3
            assert any(g is None for _, g in source_rows)
    
            # Destination geometry table.
            cursor.execute(f"IF OBJECT_ID('{dst}', 'U') IS NOT NULL DROP TABLE {dst}")
            cursor.execute(f"CREATE TABLE {dst} (id INT NOT NULL, g geometry NULL)")
            cursor.connection.commit()
    
            # Bulk copy the UDT bytes into the geometry column. Requires the GH-667
            # fix in the bundled mssql_py_core (both the varbinary(max) wire mapping
            # and the bytes->UDT value-coercion). Pre-fix this failed with
            # "Unsupported TDS type for bulk copy: 0xF0" / a bad varbinary(-1) type /
            # a "target SQL type is Udt" coercion error.
>           result = cursor.bulkcopy(dst, source_rows, timeout=60)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/test_019_bulkcopy.py:508: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <mssql_python.cursor.Cursor object at 0x111d4bce0>
table_name = 'mssql_python_bcp_udt_dst'
data = [(1, b'\x00\x00\x00\x00\x01\x0c\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@'), (2, b'\x00\x00\x00\x00\x0...\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x01\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x03')]
batch_size = 0, timeout = 60, column_mappings = None, keep_identity = False
check_constraints = False, table_lock = False, keep_nulls = False
fire_triggers = False, use_internal_transaction = False

    def bulkcopy(
        self,
        table_name: str,
        data: Iterable[Union[Tuple, "Row"]],
        batch_size: int = 0,
        timeout: int = 30,
        column_mappings: Optional[Union[List[str], List[Tuple[int, str]]]] = None,
        keep_identity: bool = False,
        check_constraints: bool = False,
        table_lock: bool = False,
        keep_nulls: boo
... [The stack trace has been truncated as it exceeded the maximum allowed size. Please refer to the complete log available in the Test Run attachments for full details.]