0

Oracle 18c:

I can get SDO_ORDINATE_ARRAY values from SDO_GEOMETRY objects:

create table test_table (shape sdo_geometry);

insert into test_table (shape) values (sdo_geometry('linestring(10 20, 30 40, 50 60)'));
insert into test_table (shape) values (sdo_geometry('linestring(70 80, 90 100)'));
insert into test_table (shape) values (sdo_geometry('linestring(110 120, 130 140, 150 160, 170 180)'));

select
    (shape).sdo_ordinates as sdo_ordinate_array
from
    test_table


SDO_ORDINATE_ARRAY
------------------
MDSYS.SDO_ORDINATE_ARRAY(10, 20, 30, 40, 50, 60)
MDSYS.SDO_ORDINATE_ARRAY(70, 80, 90, 100)
MDSYS.SDO_ORDINATE_ARRAY(110, 120, 130, 140, 150, 160, 170, 180)

db<>fiddle

For what it's worth, this is what the definition of the MDSYS.SDO_ORDINATE_ARRAY type looks like in SQL Developer:

create or replace TYPE SDO_ORDINATE_ARRAY AS VARRAY(1048576) OF NUMBER  

Using a function, I want to convert the SDO_ORDINATE_ARRAYs to the built-in VARRAY datatype.

Reason: I want to experiment with storing the ordinates in a non-spatial Function-Based Index. If I understand correctly, only built-in datatypes are supported by FBIs, not Oracle-supplied types or abstract datatypes like SDO_ORDINATE_ARRAY or SDO_GEOMETRY.

For example, if I were to try to create the following FBI, it would fail:

create index sdo_ordinates_idx on test_table ((shape).sdo_ordinates);

Error:

Error starting at line : 12 in command -
create index sdo_ordinates_idx on test_table ((shape).sdo_ordinates)
Error report -
ORA-02327: cannot create index on expression with datatype ADT     ADT=Abstract Datatype
02327. 00000 -  "cannot create index on expression with datatype %s"
*Cause:    An attempt was made to create an index on a non-indexable
           expression.
*Action:   Change the column datatype or do not create the index on an
           expression whose datatype is one of  VARRAY, nested table, object,
           LOB, or  REF.

So I can't create an FBI on SDO_ORDINATE_ARRAY. But I'm hoping I can convert the ordinates to a regular VARRAY instead and make an FBI on those values.


Question:

Is there a way to convert SDO_ORDINATE_ARRAYs to built-in VARRAYs? (for the purpose of a function-based index)

I would prefer to store the ordinates as a proper VARRAYs, rather than convert them to text. Reason: I believe the SDO_GEOMETRY constructor only accepts array values, not text.

User1974
  • 276
  • 1
  • 17
  • 63

1 Answers1

1

You state:

the definition of the MDSYS.SDO_ORDINATE_ARRAY type looks like in SQL Developer:

create or replace TYPE SDO_ORDINATE_ARRAY AS VARRAY(1048576) OF NUMBER

and then ask:

Is there a way to convert SDO_ORDINATE_ARRAYs to built-in VARRAYs? (for the purpose of a function-based index)

It is already a VARRAY, you do not need to convert it.

However

The error message states:

Error report -
ORA-02327: cannot create index on expression with datatype ADT     > ADT=Abstract Datatype
02327. 00000 -  "cannot create index on expression with datatype %s"
*Cause:    An attempt was made to create an index on a non-indexable
           expression.
*Action:   Change the column datatype or do not create the index on an
           expression whose datatype is one of VARRAY, nested table, object,
           LOB, or  REF.

In the action section it specifically states that you cannot create an index on an expression whose datatype is one of VARRAY or nested table. So what you are asking is impossible; you cannot create an index on a VARRAY.

Finally

You state:

I would prefer to store the ordinates as a proper VARRAYs, rather than convert them to text. Reason: I believe the SDO_GEOMETRY constructor only accepts array values, not text.

Looking at the source:

select text
from   all_source
where  type  = 'TYPE'
and    owner = 'MDSYS'
and    name  = 'SDO_GEOMETRY'
ORDER BY line

The MDSYS_SDO_GEOMETRY type has the constructors:

   ADD CONSTRUCTOR FUNCTION SDO_GEOMETRY(wkt IN CLOB,
     srid IN INTEGER DEFAULT NULL) RETURN SELF AS RESULT
     DETERMINISTIC PARALLEL_ENABLE,
   ADD CONSTRUCTOR FUNCTION SDO_GEOMETRY(wkt IN VARCHAR2,
     srid IN INTEGER DEFAULT NULL) RETURN SELF AS RESULT
     DETERMINISTIC PARALLEL_ENABLE,
   ADD CONSTRUCTOR FUNCTION SDO_GEOMETRY(wkb IN BLOB,
     srid IN INTEGER DEFAULT NULL) RETURN SELF AS RESULT
     DETERMINISTIC PARALLEL_ENABLE,
   ADD CONSTRUCTOR FUNCTION SDO_GEOMETRY(input_clob IN clob,
     auxiliary_info IN varchar2, crs IN VARCHAR2 DEFAULT NULL)
     RETURN SELF AS RESULT DETERMINISTIC PARALLEL_ENABLE,
   ADD CONSTRUCTOR FUNCTION SDO_GEOMETRY(input_vchar IN varchar2,
     auxiliary_info IN varchar2, crs IN VARCHAR2 DEFAULT NULL)
     RETURN SELF AS RESULT DETERMINISTIC PARALLEL_ENABLE
   CASCADE

None of those constructors take a VARRAY argument. They all take strings (VARCHAR2 or CLOB) except for one that takes a BLOB.

db<>fiddle here

MT0
  • 143,790
  • 11
  • 59
  • 117
  • Thanks. What I had in mind was: constructing an SDO_GEOEMTRY via it's attributes: `SDO_GEOMETRY(2002, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 2, 1), SDO_ORDINATE_ARRAY(10, 20, 30, 40, 50, 60))`. I had planned on using a `VARRAY` in place of `SDO_ORDINATE_ARRAY(10, 20, 30, 40, 50, 60)`. I suppose there isn't a separate constructor function for that technique. Do you concur? – User1974 Jul 08 '22 at 23:34
  • @User1974 [The documentation](https://docs.oracle.com/database/121/SPATL/sdo_geometry-constructors.htm#SPATL501) does not list any constructors like that and neither does the source. – MT0 Jul 09 '22 at 12:12
  • Yeah, I've noticed it's missing from the docs too. But it does seem to work: https://dbfiddle.uk/?rdbms=oracle_18&fiddle=d8dd0dff5edc070dc03c5a26b6a749de. I've asked the Oracle Spatial team to add it to the docs: [Idea: Add info to SDO_GEOMETRY Constructors docs (construct via object type/attributes)](https://community.oracle.com/tech/apps-infra/discussion/4499812/idea-add-info-to-sdo-geometry-constructors-docs-construct-via-object-type-attributes). – User1974 Jul 09 '22 at 14:17