FEAT: Add spatial type support (geography, geometry, hierarchyid) #422
Build #pr-validation-pipeline had test failures
Details
- Failed: 102 (0.41%)
- Passed: 23,987 (96.78%)
- Other: 697 (2.81%)
- Total: 24,786
Annotations
Check failure on line 1967 in Build log
azure-pipelines / MSSQL-Python-PR-Validation
Build log #L1967
Bash exited with code '1'.
Check failure on line 1974 in Build log
azure-pipelines / MSSQL-Python-PR-Validation
Build log #L1974
Cmd.exe exited with code '1'.
Check failure on line 2015 in Build log
azure-pipelines / MSSQL-Python-PR-Validation
Build log #L2015
Bash exited with code '1'.
Check failure on line 1966 in Build log
azure-pipelines / MSSQL-Python-PR-Validation
Build log #L1966
Bash exited with code '1'.
Check failure on line 1 in test_geography_output_converter
azure-pipelines / MSSQL-Python-PR-Validation
test_geography_output_converter
assert 0 > 0
+ where 0 = len([])
Raw output
cursor = <mssql_python.cursor.Cursor object at 0x7f906447bed0>
db_connection = <mssql_python.connection.Connection object at 0x7f9060d7d550>
def test_geography_output_converter(cursor, db_connection):
"""Test output converter registration for geography (SQL_SS_UDT)."""
try:
cursor.execute(
"CREATE TABLE #pytest_geography_converter (id INT PRIMARY KEY IDENTITY(1,1), geo_col GEOGRAPHY NULL);"
)
db_connection.commit()
cursor.execute(
"INSERT INTO #pytest_geography_converter (geo_col) VALUES (geography::STGeomFromText(?, 4326));",
POINT_WKT,
)
db_connection.commit()
converted = []
def geography_converter(value):
if value is None:
return None
converted.append(True)
return value
db_connection.add_output_converter(ConstantsDDBC.SQL_SS_UDT.value, geography_converter)
try:
row = cursor.execute("SELECT geo_col FROM #pytest_geography_converter;").fetchone()
> assert len(converted) > 0
E assert 0 > 0
E + where 0 = len([])
tests/test_017_spatial_types.py:411: AssertionError
Check failure on line 1 in test_geography_description_metadata
azure-pipelines / MSSQL-Python-PR-Validation
test_geography_description_metadata
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'type'
Raw output
cursor = <mssql_python.cursor.Cursor object at 0x7f906447bed0>
db_connection = <mssql_python.connection.Connection object at 0x7f9060d7d550>
def test_geography_description_metadata(cursor, db_connection):
"""Test cursor.description for geography columns reports SQL_SS_UDT."""
try:
cursor.execute(
"CREATE TABLE #pytest_geography_desc (id INT PRIMARY KEY, geo_col GEOGRAPHY NULL);"
)
db_connection.commit()
cursor.execute("SELECT id, geo_col FROM #pytest_geography_desc;")
desc = cursor.description
assert len(desc) == 2
assert desc[0][0] == "id"
assert desc[1][0] == "geo_col"
> assert int(desc[1][1]) == ConstantsDDBC.SQL_SS_UDT.value
^^^^^^^^^^^^^^^
E TypeError: int() argument must be a string, a bytes-like object or a real number, not 'type'
tests/test_017_spatial_types.py:435: TypeError
Check failure on line 1 in test_geography_binary_parameter_round_trip
azure-pipelines / MSSQL-Python-PR-Validation
test_geography_binary_parameter_round_trip
mssql_python.exceptions.ProgrammingError: Driver Error: Syntax error or access violation; DDBC Error: [Microsoft][SQL Server]A .NET Framework error occurred during execution of user-defined routine or aggregate "geography":
System.FormatException: 24201: Latitude values must be between -90 and 90 degrees.
System.FormatException:
at Microsoft.SqlServer.Types.GeographyValidator.ValidatePoint(Double x, Double y, Nullable`1 z, Nullable`1 m)
at Microsoft.SqlServer.Types.Validator.BeginFigure(Double x, Double y, Nullable`1 z, Nullable`1 m)
at Microsoft.SqlServer.Typ#x00䊶翽#x00㈧攒羐ӳ#x0042000#x00䊶#x01#x00풘㺗#x00#x00ऀ#x00#x00멨¥#x00#x00䊶#x01#x00䊶翽#x00䊶翽#x00#x00#x00#x00#x00#x00#x00#x00#x00䊶翽#x00䊶翽#x00尴攙羐#x00䊶翽#x00䊶翽#x00䊶翽#x01鈀㻄#x00#x00䊶翽#x00#xFFFF#xFFFF#x00#x00䊶翽#x00攙羐#x00䊶翽#x00䬘㷿#x00#x00䊶翽#x00䊶翽#x00풠㺗#x00#x00풐㺗#x00#x00䊶翽#x00䃸¨#x00#x00䊶翽#x00침攘羐#x00䊶翽#x00䬘㷿#x00#x00䊶翽#x00䊶翽#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00翽#x00儠攻羐#x00䊶翽#x00因攗羐#x00䊶翽#x00#x00#x00#x00#x00#xFFFF㺠#x00#x00麀㷧#x00#x00†攥羐#x00풠㺗#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00풠㺗#x00#x00풐㺗#x00#x00#x03攕羐#x00#x00#x00#x00#x00谠㷂#x00#x00䊶翽#x00�攔羐#x00˰㺠#x00#x00谠㷂#x00#x00䊶翽#x00퉂攓羐#x00#x00#x00#x00#x00儠攻羐#x00䊶翽#x00䃸¨#x00#x00ް㺓#x00#x00#x05#x00#x00#x00#x06#x00#x00#x00攔羐#x00䊶翽#x00#x00#x00#x00#x00#x00#x00翽#x00�攓羐#x00䊶翽#x00蝨㸈#x00Ѐ䬘㷿#x00#x00䬘㷿#x00#x00#x00#x00#x00#x00儠攻羐#x00䊶翽#x00壈攗羐#x00˰㺠#x00#x00䊶翽#x00䊶翽#x00帥攓羐#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00�㣓茥椢䊶翽#x00#x00#x00#x00#x00⟀慱羐#x00Ố敒羐#x00#x00#x00#x00#x00#x00#x00羐#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00굀斃羐#x00#x00#x00#x00#x00䊶翽#x00#x01#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00㾀翽#x00#x00#x00#x00#x00#x00#x00#x00#x00䫠㷿#x00#x00雰㺔#x00#x00霈㺔#x00#x00霈㺔#x00#x00˰㺠#x00#x00#x00#x00羐#x00˰㺠#x00#x00#x03#x00羐#x00˸㺠#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00뫨¥#x00#x00#x00#x00#x00#x00䃸¨#x00#x00榰朅羐#x00䊶翽#x00儀敘羐#x00䊶翽#x00䃸¨#x00#x00䊶翽#x00#x00#x00#x00#x00扏T#x00#x00寀昁羐#x00멨¥#x00#x00#x00#x00#x00#x00#x03#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00䃸¨#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x01#x00#x00#x00뫨¥#x00#x00#x03#x00#x00#x00#x00#x00#x00#x00犐斐羐#x00#x00#x00#x00#x00屈T#x00#x00#x08#x000#x00#x00#x00#x00#x00䊶翽#x00楐朅羐#x00䊶翽#x00#x00#x00#x00#x00 #x00#x00#x00퇀教羐#x00ീ敍羐#x00#x10#x00#x00#x00䊶翽#x00䃸¨#x00#x00얀敖羐#x00#x00#x00#x00#x00昐羐#x00犐斐羐#x00掽羐#x00ࠅV#x00#x00ꌐ㸈#x00#x00퇀教羐#x00詐摥羐#x00ť#x00#x00#x00鸀懞羐#x00䃸¨#x00#x00犐斐羐#x00#x00#x00#x00#x00犐斐羐#x00䄵斒羐#x00賀㸈#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00ť#x00#x00#x00ť#x00#x00#x00㴐斒羐#x00䃸¨#x00
Raw output
cursor = <mssql_python.cursor.Cursor object at 0x7f906447bed0>
db_connection = <mssql_python.connection.Connection object at 0x7f9060d7d550>
def test_geography_binary_parameter_round_trip(cursor, db_connection):
"""Test binary round-trip: fetch as bytes, reinsert via STGeomFromWKB, compare WKT."""
try:
cursor.execute(
"CREATE TABLE #pytest_geography_binary (id INT PRIMARY KEY IDENTITY(1,1), geo_col GEOGRAPHY NULL);"
)
db_connection.commit()
cursor.execute(
"INSERT INTO #pytest_geography_binary (geo_col) VALUES (geography::STGeomFromText(?, 4326));",
POINT_WKT,
)
db_connection.commit()
row = cursor.execute("SELECT geo_col FROM #pytest_geography_binary;").fetchone()
original_binary = row[0]
assert isinstance(original_binary, bytes)
# Reinsert the binary via STGeomFromWKB
> cursor.execute(
"INSERT INTO #pytest_geography_binary (geo_col) VALUES (geography::STGeomFromWKB(?, 4326));",
original_binary,
)
tests/test_017_spatial_types.py:494:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
mssql_python/cursor.py:1349: in execute
check_error(ddbc_sql_const.SQL_HANDLE_STMT.value, self.hstmt, ret)
mssql_python/helpers.py:38: in check_error
raise_exception(error_info.sqlState, error_info.ddbcErrorMsg)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
sqlstate = '42000'
ddbc_error = '[Microsoft][ODBC Driver 18 for SQL Server][SQL Server]A .NET Framework error occurred during execution of user-define...犐斐羐\x00\x00\x00\x00\x00犐斐羐\x00䄵斒羐\x00賀㸈\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ť\x00\x00\x00ť\x00\x00\x00㴐斒羐\x00䃸¨\x00'
def raise_exception(sqlstate: str, ddbc_error: str) -> None:
"""
Raise a custom exception based on the given SQLSTATE code.
This function raises a custom exception based on the provided SQLSTATE code.
If the code is not found in the mapping, a generic DatabaseError is raised.
Args:
sqlstate (str): The SQLSTATE code to map to a custom exception.
ddbc_error (str): The DDBC error message.
Raises:
DatabaseError: If the SQLSTATE code is not found in the mapping.
"""
exception_class = sqlstate_to_exception(sqlstate, ddbc_error)
if exception_class:
logger.error(f"Raising exception: {exception_class}")
> raise exception_class
E mssql_python.exceptions.ProgrammingError: Driver Error: Syntax error or access violation; DDBC Error: [Microsoft][SQL Server]A .NET Framework error occurred during execution of user-defined routine or aggregate "geography":
E System.FormatException: 24201: Latitude values must be between -90 and 90 degrees.
E System.FormatException:
E at Microsoft.SqlServer.Types.GeographyValidator.ValidatePoint(Double x, Double y, Nullable`1 z, Nullable`1 m)
E at Microsoft.SqlServer.Types.Validator.BeginFigure(Double x, Double y, Nullable`1 z, Nullable`1 m)
E at Microsoft.SqlServer.Typ#x00䊶翽#x00㈧攒羐ӳ#x0042000#x00䊶#x01#x00풘㺗#x00#x00ऀ#x00#x00멨¥#x00#x00䊶#x01#x00䊶翽#x00䊶翽#x00#x00#x00#x00#x00#x00#x00#x00#x00䊶翽#x00䊶翽#x00尴攙羐#x00䊶翽#x00䊶翽#x00䊶翽#x01鈀㻄#x00#x00䊶翽#x00#xFFFF#xFFFF#x00#x00䊶翽#x00攙羐#x00䊶翽#x00䬘㷿#x00#x00䊶翽#x00䊶翽#x00풠㺗#x00#x00풐㺗#x00#x00䊶翽#x00䃸¨#x00#x00䊶翽#x00침攘羐#x00䊶翽#x00䬘㷿#x00#x00䊶翽#x00䊶翽#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00翽#x00儠攻羐#x00䊶翽#x00因攗羐#x00䊶翽#x00#x00#x00#x00#x00#xFFFF㺠#x00#x00麀㷧#x00#x00†攥羐#x00풠㺗#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00#x00풠㺗#x00#x00풐㺗#x00#x00#x03攕羐#x00#x00#x00#x00#x00谠㷂#x00#x00䊶翽#x00�攔羐#x00˰㺠#x00#x00谠㷂#x00#x00䊶翽#x00퉂攓羐#x00#x00#x00#x00#x00儠攻羐#x00䊶翽#x00䃸¨#x00#x00ް㺓#x00#x00#x05#x00#x00#x00#x06
Check failure on line 1 in test_geometry_description_metadata
azure-pipelines / MSSQL-Python-PR-Validation
test_geometry_description_metadata
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'type'
Raw output
cursor = <mssql_python.cursor.Cursor object at 0x7f906447bed0>
db_connection = <mssql_python.connection.Connection object at 0x7f9060d7d550>
def test_geometry_description_metadata(cursor, db_connection):
"""Test cursor.description for geometry columns reports SQL_SS_UDT."""
try:
cursor.execute(
"CREATE TABLE #pytest_geometry_desc (id INT PRIMARY KEY, geom_col GEOMETRY NULL);"
)
db_connection.commit()
cursor.execute("SELECT id, geom_col FROM #pytest_geometry_desc;")
desc = cursor.description
assert len(desc) == 2
assert desc[0][0] == "id"
assert desc[1][0] == "geom_col"
> assert int(desc[1][1]) == ConstantsDDBC.SQL_SS_UDT.value
^^^^^^^^^^^^^^^
E TypeError: int() argument must be a string, a bytes-like object or a real number, not 'type'
tests/test_017_spatial_types.py:701: TypeError