Top 5 Recent Articles
ARTICLES CATEGORIES
- Algorithms (22)
- All (399)
- Biography (1)
- Blog (44)
- Business Requirements (1)
- Commentary (1)
- Conversion (2)
- Customers (2)
- Data Models (1)
- Education (2)
- GeoRaptor (13)
- GPS (1)
- Image Processing (2)
- Import Export (8)
- Licensing (2)
- LiDAR (1)
- Linear Referencing (4)
- Manifold GIS (3)
- Mapping (1)
- MySQL Spatial (7)
- Networking and Routing (including Optimization) (5)
- Open Source (18)
- Oracle Spatial and Locator (194)
- Partitioning (1)
- PostGIS (36)
- Projections (1)
- Published Articles (1)
- qGIS (1)
- Recommendations (1)
- Services (1)
- Software Change Log (1)
- Source Code (37)
- Space Curves (9)
- Spatial Database Functions (109)
- Spatial DB comparison (1)
- Spatial XML Processing (11)
- SQL Server Spatial (92)
- Standards (3)
- Stored Procedure (17)
- Tessellation or Gridding (10)
- Tools (2)
- Topological Relationships (1)
- Training (2)
- Triangulation (2)
ORA-13011 errors when using SDO_GEOM.VALIDATE_LAYER_WITH_CONTEXT()
I was sent a request for help the other day from some I know overseas:
Do you know the true meaning and impact of ‘ORA-13011 value is out of range’? I have a dataset with a lot of very (almost impossible) precise data coming from Bentley microstation. And we have a ‘businessrule’ that the default tolerance in all the tables is 0.005. Any suggestion how to react on a ORA-13011 error when using sdo_geom.validate_layer_with_context
What was not said till a later email was that (my italics highlight what I suspected):
We use FME to transform … DGN-files to Oracle Spatial. An existing table is truncated and refilled with geometries. Because the tables already exist, they are already registered in de user_metadata and FME is not updating it.
Answer
Let’s construct an example that you can all try that shows this problem.
First, let’s create a 10,000 rectangular polygons inside this area.
+————————+ 608222 5497524
| |
| |
| |
| |
| |
| |
294829 5162028 +————————+
DROP TABLE rectangles; DROP TABLE rectangles succeeded. CREATE TABLE rectangles ( rect_id Integer primary key, geometry mdsys.sdo_geometry ); CREATE TABLE succeeded. INSERT /*+APPEND*/ INTO rectangles (rect_id,geometry) SELECT rownum as rect_id, mdsys.sdo_geometry(2003,28355,NULL,mdsys.sdo_elem_info_array(1,1003,3), MDSYS.SDO_ORDINATE_ARRAY(ROUND(w.x - (w.rectWidth/2),w.rndf), ROUND(w.y - (w.rectHeight/2),w.rndf), ROUND(w.x + (w.rectWidth/2),w.rndf), ROUND(w.y + (w.rectHeight/2),w.rndf) ) ) as geometry FROM ( SELECT ROUND(dbms_random.value(w.x - ( w.WinWidth / 2 ), w.x + ( w.WinWidth / 2 )),w.rndf) as x, ROUND(dbms_random.value(w.y - ( w.WinHeight / 2 ), w.y + ( w.WinHeight / 2 )),w.rndf) as y, dbms_random.value(50, 1000) as rectWidth, dbms_random.value(50, 1000) as rectHeight, w.rndf FROM ( SELECT ( 294000 + 609000 ) / 2 as X, ( 5162000 + 5498000 ) / 2 as y, ( 5498000 - 5162000 ) as WinHeight, ( 609000 - 294000 ) as WinWidth, 10000 as RectCount, ROUND(log(10,1/0.05))+1 as rndf FROM DUAL ) w, TABLE(CAST(MULTISET(select level from dual connect by level <= w.RectCount) as SYS.UTL_NLA_ARRAY_INT)) s ) w; 10000 rows inserted ALTER TABLE rectangles LOGGING; ALTER TABLE rectangles succeeded. COMMIT; commited
Let’s summary what was inserted into the table…
SELECT count(*) || ' rectangles were stored' As Result FROM rectangles; RESULT --------------------------------------------------------------- 10000 rectangles were stored
Now, let’s create an Oracle Metadata entry that is DELIBERATELY too small.
DELETE FROM user_sdo_geom_metadata WHERE table_name = 'RECTANGLES'; 1 rows deleted COMMIT; commited INSERT INTO user_sdo_geom_metadata ( table_name, column_name, diminfo, srid ) VALUES ( 'RECTANGLES', 'GEOMETRY', MDSYS.SDO_DIM_ARRAY( MDSYS.SDO_DIM_ELEMENT( 'X', ( ( 294000 + 609000 ) / 2 ) - 1000, ( ( 294000 + 609000 ) / 2 ) + 1000, 0.05), MDSYS.SDO_DIM_ELEMENT( 'Y', ( ( 5162000 + 5498000 ) / 2 ) - 1000, ( ( 5162000 + 5498000 ) / 2 ) + 1000, 0.05) ), 28355 ); 1 rows inserted COMMIT; commited
Now, let’s run SDO_GEOM.VALIDATE_LAYER_WITH_CONTEXT;
DROP TABLE rectangles_v; DROP TABLE rectangles_v succeeded. CREATE TABLE rectangles_v (sdo_rowid ROWID, result varchar2(1000)); CREATE TABLE succeeded. EXECUTE SDO_GEOM.VALIDATE_LAYER_WITH_CONTEXT('RECTANGLES','GEOMETRY','RECTANGLES_V'); anonymous block completed SELECT result, count(*) as rcount FROM rectangles_v GROUP BY result; RESULT RCOUNT ------------------------- ----- 13011 10000 Rows Processed <10000> 1 2 rows selected
This indicates that of the 10,000 rectangles processed all are invalid (see following) as “The result table contains one row for each invalid geometry”.
As a check, let’s run SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT() on a 10% sample of all the rectangles in the table:
SELECT DISTINCT SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(a.geometry,b.diminfo) FROM RECTANGLES SAMPLE (10) a, user_sdo_geom_metadata b WHERE b.table_name = 'RECTANGLES' AND b.column_name = 'GEOMETRY'; SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(A.GEOMETRY,B.DIMINFO) ------------------------------------------------------------- 13011 1 rows selected
Notice how, in both cases, we get the Oracle error 13011 which is:
ORA-13011: value is out of range Cause: A specified dimension value is outside the range defined for that dimension. Action: Make sure that all values to be encoded are within the defined dimension range.
Now, let’s change the user_sdo_geom_metadata to be correct by calculating it from the actual data….
UPDATE user_sdo_geom_metadata SET diminfo = ( SELECT MDSYS.SDO_DIM_ARRAY( MDSYS.SDO_DIM_ELEMENT('X', minx, maxx, 0.05), MDSYS.SDO_DIM_ELEMENT('Y', miny, maxy, 0.05)) as diminfo FROM ( SELECT TRUNC( MIN( v.x ) - 1,0) as minx, ROUND( MAX( v.x ) + 1,0) as maxx, TRUNC( MIN( v.y ) - 1,0) as miny, ROUND( MAX( v.y ) + 1,0) as maxy FROM (SELECT SDO_AGGR_MBR(a.geometry) as mbr FROM rectangles a) b, TABLE(mdsys.sdo_util.getvertices(b.mbr)) v ) ) WHERE table_name = 'RECTANGLES' AND column_name = 'GEOMETRY'; 1 rows updated COMMIT; commited
Now, let’s re-run the validate_layer_with_context….
DROP TABLE rectangles_v; DROP TABLE rectangles_v succeeded. CREATE TABLE rectangles_v (sdo_rowid ROWID, result varchar2(1000)); CREATE TABLE succeeded. EXECUTE SDO_GEOM.VALIDATE_LAYER_WITH_CONTEXT('RECTANGLES','GEOMETRY','RECTANGLES_V'); anonymous block completed SELECT result, count(*) as rcount FROM rectangles_v GROUP BY result; RESULT RCOUNT ------------------------- ------ Rows Processed <10000> 1 2 rows selected
SDO_GEOM.VALIDATE_LEYER_WITH_CONTEXT does not write a row if a geometry is valid. There are no rows in the table other than the row that is written indicating how many rows have been processed.
This can be checked by running SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT() against the whole layer in an ordinary SQL statement:
SELECT DISTINCT SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(a.geometry,b.diminfo) FROM RECTANGLES a, user_sdo_geom_metadata b WHERE b.table_name = 'RECTANGLES' AND b.column_name = 'GEOMETRY'; SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(A.GEOMETRY,B.DIMINFO) ------------------------------------------------------------- TRUE 1 rows selected
I hope this is of help to someone.
Documentation
- MySQL Spatial General Functions
- Oracle LRS Objects
- Oracle Spatial Exporter (Java + pl/SQL)
- Oracle Spatial Object Functions
- Oracle Spatial Object Functions (Multi Page)
- PostGIS pl/pgSQL Functions
- SC4O Oracle Java Topology Suite (Java + pl/SQL)
- SQL Server Spatial General TSQL Functions
- SQL Server Spatial LRS TSQL Functions