Go to content Go to navigation and search

Home

Current Oracle Spatial Blog Articles


Search

Browse

RSS / Atom

Email me

textpattern

Creative Commons License
All Blog Articles, Data Models and Free Source Code by Simon Greener, The SpatialDB Advisor is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

ORA-13011 errors when using SDO_GEOM.VALIDATE_LAYER_WITH_CONTEXT()

Monday December 07 2009 at 17:36

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.

Creative Commons License

post this at del.icio.uspost this at Diggpost this at Technoratipost this at Redditpost this at Farkpost this at Yahoo! my webpost this at Windows Livepost this at Google Bookmarkspost this to Twitter

Comment