sqloracleoracle18coracle-spatial

Determine what rows are causing error in query


I have an Oracle 18c table that has 15,000 rows. As a test, I'm trying to run the following query on it:

select
    --works for all rows:
    --sdo_util.to_wkbgeometry(sdo_geometry(replace(sde.st_astext(shape),'LINESTRING M','LINESTRING')))
    
    --doesn't work for all rows (the problem is caused by: SDO_UTIL.FROM_WKBGEOMETRY() ):
    sdo_util.from_wkbgeometry(sdo_util.to_wkbgeometry(sdo_geometry(replace(sde.st_astext(shape),'LINESTRING M','LINESTRING'))))
from
    my_table;

When I run that query in SQL Developer, it initially runs without errors, but that's just because it's only selecting the first 50 rows.

If I try to run the query on all rows (via CTRL+END), then it throws an error:

ORA-29532: Java call terminated by uncaught Java exception: java.lang.RuntimeException: oracle.spatial.util.GeometryExceptionWithContext: Byte order can only be either BIG_ENDIAN (encoded as 0) or LITTLE_ENDIAN (encoded as 1). Found encoding 65
ORA-06512: at "MDSYS.SDO_JAVA_STP", line 68
ORA-06512: at "MDSYS.SDO_UTIL", line 6244
29532. 00000 -  "Java call terminated by uncaught Java exception: %s"
*Cause:    A Java exception or error was signaled and could not be
           resolved by the Java code.
*Action:   Modify Java code, if this behavior is not intended.

How can I determine what specific rows are causing that error?

I tried using SDO_UTIL.VALIDATE_WKBGEOMETRY() to find the problem blobs. But, surprisingly, it didn't return any FALSE values.


Solution

  • Create a function to wrap the call that is causing issues and catch the exception in the function:

    CREATE FUNCTION test_from_wkbgeometry(
      v_data IN BLOB
    ) RETURN NUMBER
    IS
      temp SDO_GEOMETRY;
    BEGIN
      temp := sdo_util.from_wkbgeometry(v_data);
      RETURN 1;
    EXCEPTION
      WHEN OTHERS THEN
        RETURN 0;
    END;
    /
    

    Then use it in your query:

    SELECT *
    FROM   my_table
    WHERE  test_from_wkbgeometry(
             sdo_util.to_wkbgeometry(
               sdo_geometry(replace(sde.st_astext(shape),'LINESTRING M','LINESTRING'))
             )
           ) = 0;
    

    In later Oracle versions, you can define the function in the query:

    WITH FUNCTION test_from_wkbgeometry(
      v_data IN BLOB
    ) RETURN NUMBER
    IS
      temp SDO_GEOMETRY;
    BEGIN
      temp := sdo_util.from_wkbgeometry(v_data);
      RETURN 1;
    EXCEPTION
      WHEN OTHERS THEN
        RETURN 0;
    END;
    SELECT *
    FROM   my_table
    WHERE  test_from_wkbgeometry(
             sdo_util.to_wkbgeometry(
               sdo_geometry(replace(sde.st_astext(shape),'LINESTRING M','LINESTRING'))
             )
           ) = 0;