1 /******************************************************************************
2  * $Id: ogr_oci.h fa752ad6eabafaf630a704e1892a9d837d683cb3 2021-03-06 17:04:38 +0100 Even Rouault $
3  *
4  * Project:  Oracle Spatial Driver
5  * Purpose:  Oracle Spatial OGR Driver Declarations.
6  * Author:   Frank Warmerdam <warmerdam@pobox.com>
7  *
8  ******************************************************************************
9  * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included
19  * in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  ****************************************************************************/
29 
30 #ifndef OGR_OCI_H_INCLUDED
31 #define OGR_OCI_H_INCLUDED
32 
33 #include "ogrsf_frmts.h"
34 #include "oci.h"
35 #include "cpl_error.h"
36 
37 /* -------------------------------------------------------------------- */
38 /*      Low level Oracle spatial declarations.                          */
39 /* -------------------------------------------------------------------- */
40 #define TYPE_OWNER                 "MDSYS"
41 #define SDO_GEOMETRY               "MDSYS.SDO_GEOMETRY"
42 
43 typedef struct
44 {
45    OCINumber x;
46    OCINumber y;
47    OCINumber z;
48 } sdo_point_type;
49 
50 typedef OCIArray sdo_elem_info_array;
51 typedef OCIArray sdo_ordinate_array;
52 
53 typedef struct
54 {
55    OCINumber      sdo_gtype;
56    OCINumber      sdo_srid;
57    sdo_point_type sdo_point;
58    OCIArray       *sdo_elem_info;
59    OCIArray       *sdo_ordinates;
60 } SDO_GEOMETRY_TYPE;
61 
62 typedef struct
63 {
64    OCIInd _atomic;
65    OCIInd x;
66    OCIInd y;
67    OCIInd z;
68 } sdo_point_type_ind;
69 
70 typedef struct
71 {
72    OCIInd                    _atomic;
73    OCIInd                    sdo_gtype;
74    OCIInd                    sdo_srid;
75    sdo_point_type_ind        sdo_point;
76    OCIInd                    sdo_elem_info;
77    OCIInd                    sdo_ordinates;
78 } SDO_GEOMETRY_ind;
79 
80 #define ORA_GTYPE_MATCH(a,b)      ( ((a) % 100) == ((b) % 100))
81 #define ORA_GTYPE_UNKNOWN         0
82 #define ORA_GTYPE_POINT           1
83 #define ORA_GTYPE_LINESTRING      2    // or curve
84 #define ORA_GTYPE_POLYGON         3    // or surface
85 #define ORA_GTYPE_COLLECTION      4
86 #define ORA_GTYPE_MULTIPOINT      5
87 #define ORA_GTYPE_MULTILINESTRING 6    // or multicurve
88 #define ORA_GTYPE_MULTIPOLYGON    7    // or multisurface
89 #define ORA_GTYPE_SOLID           8
90 #define ORA_GTYPE_MULTISOLID      9
91 
92 #define DEFAULT_STRING_SIZE       4000
93 
94 /************************************************************************/
95 /*                            OGROCISession                             */
96 /************************************************************************/
97 class CPL_DLL OGROCISession {
98   public:
99     OCIEnv     *hEnv;
100     OCIError   *hError;
101     OCISvcCtx  *hSvcCtx;
102     OCIServer  *hServer;
103     OCISession *hSession;
104     OCIDescribe*hDescribe;
105     OCIType    *hGeometryTDO;
106     OCIType    *hOrdinatesTDO;
107     OCIType    *hElemInfoTDO;
108 
109     char       *pszUserid;
110     char       *pszPassword;
111     char       *pszDatabase;
112 
113   public:
114              OGROCISession();
115     virtual ~OGROCISession();
116 
117     int      EstablishSession( const char *pszUserid,
118                                const char *pszPassword,
119                                const char *pszDatabase );
120 
121     int      Failed( sword nStatus, const char *pszFunction = nullptr );
122 
123     CPLErr   GetParamInfo( OCIParam *hParamDesc, OGRFieldDefn *poOGRDefn,
124                           ub2 *pnOCIType, ub4 *pnOCILen );
125 
126     void     CleanName( char * );
127 
128     OCIType *PinTDO( const char * );
129 
130   private:
131 
132     int         nServerVersion;
133     int         nServerRelease;
134     size_t      nMaxNameLength;
135 };
136 
137 OGROCISession CPL_DLL*
138 OGRGetOCISession( const char *pszUserid,
139                   const char *pszPassword,
140                   const char *pszDatabase );
141 
142 /************************************************************************/
143 /*                           OGROCIStatement                            */
144 /************************************************************************/
145 class CPL_DLL OGROCIStatement {
146   public:
147     explicit     OGROCIStatement( OGROCISession * );
148     virtual     ~OGROCIStatement();
149 
GetStatement()150     OCIStmt     *GetStatement() { return hStatement; }
151     CPLErr       BindScalar( const char *pszPlaceName,
152                              void *pData, int nDataLen, int nSQLType,
153                              sb2 *paeInd = nullptr );
154     CPLErr       BindString( const char *pszPlaceName,
155                              const char *pszData,
156                              sb2 *paeInd = nullptr );
157     CPLErr       BindObject( const char *pszPlaceName, void *pahObject,
158                              OCIType *hTDO, void **papIndicators );
159 
160     char        *pszCommandText;
161 
162     CPLErr       Prepare( const char * pszStatement );
163     CPLErr       Execute( const char * pszStatement,
164                           int nMode = -1 );
165     void         Clean();
166 
GetResultDefn()167     OGRFeatureDefn *GetResultDefn() { return poDefn; }
168 
169     char       **SimpleFetchRow();
170 
GetAffectedRows()171     int          GetAffectedRows() const { return nAffectedRows; }
172 
173   private:
174     OGROCISession *poSession;
175     OCIStmt       *hStatement;
176 
177     OGRFeatureDefn*poDefn;
178 
179     char         **papszCurColumn;
180     char         **papszCurImage;
181     sb2          *panCurColumnInd;
182 
183     int           nRawColumnCount;
184     int           *panFieldMap;
185     int           nAffectedRows;
186 };
187 
188 /************************************************************************/
189 /*                           OGROCIStringBuf                            */
190 /************************************************************************/
191 class OGROCIStringBuf
192 {
193   char *pszString;
194   int  nLen;
195   int  nBufSize;
196 
197   void UpdateEnd();
198 
199 public:
200 
201     OGROCIStringBuf();
202     ~OGROCIStringBuf();
203 
204     void MakeRoomFor( int );
205     void Append( const char * );
206     void Appendf( int nMax, const char *pszFormat, ... ) CPL_PRINT_FUNC_FORMAT (3, 4);
207     char *StealString();
208 
209     char GetLast();
GetEnd()210     char *GetEnd() { UpdateEnd(); return pszString + nLen; }
GetString()211     char *GetString() { return pszString; }
212 
213     void Clear();
214 };
215 
216 /************************************************************************/
217 /*                             OGROCILayer                              */
218 /************************************************************************/
219 
220 class OGROCIDataSource;
221 
222 class OGROCILayer CPL_NON_FINAL: public OGRLayer
223 {
224   protected:
225     OGRFeatureDefn     *poFeatureDefn;
226 
227     int                 iNextShapeId;
228 
229     OGROCIDataSource    *poDS;
230 
231     char               *pszQueryStatement;
232 
233     int                 nResultOffset;
234 
235     OGROCIStatement    *poStatement;
236 
237     int                 ExecuteQuery( const char * );
238 
239     SDO_GEOMETRY_TYPE  *hLastGeom;
240     SDO_GEOMETRY_ind   *hLastGeomInd;
241 
242     char               *pszGeomName;
243     int                iGeomColumn;
244 
245     char               *pszFIDName;
246     int                iFIDColumn;
247 
248     OGRGeometry        *TranslateGeometry();
249     OGRGeometry        *TranslateGeometryElement( int *piElement,
250                                                   int nGType, int nDimension,
251                                                   int nEType,
252                                                   int nInterpretation,
253                                                   int nStartOrdinal,
254                                                   int nOrdCount);
255     int      LoadElementInfo( int iElement, int nElemCount, int nTotalOrdCount,
256                               int *pnEType, int *pnInterpretation,
257                               int *pnStartOrdinal, int *pnElemOrdCount );
258     int                 GetOrdinalPoint( int iOrdinal, int nDimension,
259                                          double *pdfX, double *pdfY,
260                                          double *pdfZ );
261 
262   public:
263                         OGROCILayer();
264     virtual             ~OGROCILayer();
FindFieldIndex(const char * pszFieldName,int bExactMatch)265     virtual int         FindFieldIndex( const char *pszFieldName, int bExactMatch ) override { return OGRLayer::FindFieldIndex( pszFieldName, bExactMatch ); }
266 
267     virtual void        ResetReading() override;
268     virtual OGRFeature *GetNextRawFeature();
269     virtual OGRFeature *GetNextFeature() override;
270 
GetLayerDefn()271     OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
272 
273     virtual int         TestCapability( const char * ) override;
274 
275     virtual const char *GetFIDColumn() override;
276     virtual const char *GetGeometryColumn() override;
277 
278     int                 LookupTableSRID();
279 };
280 
281 /************************************************************************/
282 /*                         OGROCIWritableLayer                          */
283 /************************************************************************/
284 
285 class OGROCIWritableLayer CPL_NON_FINAL: public OGROCILayer
286 {
287 protected:
288     int                 nDimension;
289     int                 nSRID;
290 
291     int                 nOrdinalCount;
292     int                 nOrdinalMax;
293     double             *padfOrdinals;
294 
295     int                 nElemInfoCount;
296     int                 nElemInfoMax;
297     int                *panElemInfo;
298 
299     void                PushOrdinal( double );
300     void                PushElemInfo( int, int, int );
301 
302     OGRErr              TranslateToSDOGeometry( OGRGeometry *,
303                                                 int *pnGType );
304     OGRErr              TranslateElementGroup( OGRGeometry *poGeometry );
305 
306     int                 bLaunderColumnNames;
307     int                 bPreservePrecision;
308     int                 nDefaultStringSize;
309 
310     OGRSpatialReference *poSRS;
311 
312     char              **papszOptions;
313 
314     int                 bTruncationReported;
315     void                ReportTruncation( OGRFieldDefn * );
316 
317     void                ParseDIMINFO( const char *, double *, double *,
318                                       double * );
319 
320                         OGROCIWritableLayer();
321     virtual            ~OGROCIWritableLayer();
322 public:
323 
GetSpatialRef()324     virtual OGRSpatialReference *GetSpatialRef() override { return poSRS; }
325     virtual OGRErr      CreateField( OGRFieldDefn *poField,
326                                      int bApproxOK = TRUE ) override;
327     virtual int         FindFieldIndex( const char *pszFieldName, int bExactMatch ) override;
328 
329     // following methods are not base class overrides
330     void                SetOptions( char ** );
331 
332     void                SetDimension( int );
SetLaunderFlag(int bFlag)333     void                SetLaunderFlag( int bFlag )
334                                 { bLaunderColumnNames = bFlag; }
SetPrecisionFlag(int bFlag)335     void                SetPrecisionFlag( int bFlag )
336                                 { bPreservePrecision = bFlag; }
SetDefaultStringSize(int nSize)337     void                SetDefaultStringSize( int nSize )
338                                 { nDefaultStringSize = nSize; }
339 };
340 
341 /************************************************************************/
342 /*                          OGROCILoaderLayer                           */
343 /************************************************************************/
344 
345 #define LDRM_UNKNOWN  0
346 #define LDRM_STREAM   1
347 #define LDRM_VARIABLE 2
348 #define LDRM_BINARY   3
349 
350 class OGROCILoaderLayer final: public OGROCIWritableLayer
351 {
352     OGREnvelope         sExtent;
353     int                 iNextFIDToWrite;
354 
355     char                *pszLoaderFilename;
356 
357     FILE                *fpLoader;
358     int                 bHeaderWritten;
359 
360     FILE                *fpData;
361 
362     int                 nLDRMode;
363 
364     void                WriteLoaderHeader();
365     void                FinalizeNewLayer();
366 
367     OGRErr              WriteFeatureStreamMode( OGRFeature * );
368     OGRErr              WriteFeatureVariableMode( OGRFeature * );
369     // cppcheck-suppress functionStatic
370     OGRErr              WriteFeatureBinaryMode( OGRFeature * );
371 
372   public:
373                         OGROCILoaderLayer( OGROCIDataSource *,
374                                            const char * pszName,
375                                            const char *pszGeomCol,
376                                            int nSRID,
377                                            const char *pszLoaderFile );
378                         virtual ~OGROCILoaderLayer();
379 
380     virtual void        ResetReading() override;
381     virtual GIntBig     GetFeatureCount( int ) override;
382 
SetSpatialFilter(OGRGeometry *)383     virtual void        SetSpatialFilter( OGRGeometry * ) override {}
SetSpatialFilter(int iGeomField,OGRGeometry * poGeom)384     virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
385                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
386 
SetAttributeFilter(const char *)387     virtual OGRErr      SetAttributeFilter( const char * ) override
388                                 { return OGRERR_UNSUPPORTED_OPERATION; }
389 
390     virtual OGRFeature *GetNextFeature() override;
391 
392     virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
393 
GetSpatialRef()394     virtual OGRSpatialReference *GetSpatialRef() override { return poSRS; }
395 
396     virtual int         TestCapability( const char * ) override;
397 };
398 
399 /************************************************************************/
400 /*                           OGROCITableLayer                            */
401 /************************************************************************/
402 
403 class OGROCITableLayer final: public OGROCIWritableLayer
404 {
405     int                 bUpdateAccess;
406     int                 bNewLayer;
407     OGREnvelope         sExtent;
408     bool                bExtentUpdated;
409 
410     int                 iNextFIDToWrite;
411     int                 bHaveSpatialIndex;
412 
413     OGRFeatureDefn     *ReadTableDefinition(const char *);
414 
415     void                BuildWhere();
416     char               *BuildFields();
417     void                BuildFullQueryStatement();
418 
419     char               *pszQuery;
420     char               *pszWHERE;
421 
422     int                 bValidTable;
423 
424     CPLString           osTableName;
425     CPLString           osOwner;
426 
427     int                 nFirstId;
428     int                 nMultiLoadCount;
429     int                 bMultiLoad;
430 
431     OCIArray           *hOrdVARRAY;
432     OCIArray           *hElemInfoVARRAY;
433 
434     void                UpdateLayerExtents();
435     void                CreateSpatialIndex();
436 
437     void                TestForSpatialIndex( const char * );
438 
439     OGROCIStatement   *poBoundStatement;
440 
441     int                 nWriteCacheMax;
442     int                 nWriteCacheUsed;
443 
444     SDO_GEOMETRY_TYPE  *pasWriteGeoms;
445     SDO_GEOMETRY_TYPE **papsWriteGeomMap;
446     SDO_GEOMETRY_ind   *pasWriteGeomInd;
447     SDO_GEOMETRY_ind  **papsWriteGeomIndMap;
448 
449     void              **papWriteFields;
450     OCIInd            **papaeWriteFieldInd;
451     int                *panWriteFIDs;
452 
453     int                 AllocAndBindForWrite();
454     OGRErr              FlushPendingFeatures();
455 
456     OGRErr              UnboundCreateFeature( OGRFeature *poFeature );
457     OGRErr              BoundCreateFeature( OGRFeature *poFeature );
458 
459   public:
460                         OGROCITableLayer( OGROCIDataSource *,
461                                           const char * pszName, OGRwkbGeometryType eGType,
462                                           int nSRID, int bUpdate, int bNew );
463                         virtual ~OGROCITableLayer();
464 
465     virtual void        ResetReading() override;
466     virtual GIntBig     GetFeatureCount( int ) override;
467 
468     virtual void        SetSpatialFilter( OGRGeometry * ) override;
SetSpatialFilter(int iGeomField,OGRGeometry * poGeom)469     virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
470                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
471 
472     virtual OGRErr      SetAttributeFilter( const char * ) override;
473 
474     virtual OGRFeature *GetNextFeature() override;
475     virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
476 
477     virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
478     virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
479     virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
480 
481     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
GetExtent(int iGeomField,OGREnvelope * psExtent,int bForce)482     virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
483                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
484 
485     virtual int         TestCapability( const char * ) override;
486 
487     virtual OGRErr      SyncToDisk() override;
488 
489     // following methods are not base class overrides
IsValid()490     int                 IsValid() { return bValidTable; }
491 
492     int                 GetMaxFID();
493 };
494 
495 /************************************************************************/
496 /*                          OGROCISelectLayer                           */
497 /************************************************************************/
498 
499 class OGROCISelectLayer final: public OGROCILayer
500 {
501     OGRFeatureDefn     *ReadTableDefinition( OGROCIStatement * poStatement );
502 
503   public:
504                         OGROCISelectLayer( OGROCIDataSource *,
505                                            const char * pszName,
506                                            OGROCIStatement *poStatement );
507                         ~OGROCISelectLayer();
508 };
509 
510 /************************************************************************/
511 /*                           OGROCIDataSource                           */
512 /************************************************************************/
513 
514 class OGROCIDataSource final: public OGRDataSource
515 {
516     OGROCILayer       **papoLayers;
517     int                 nLayers;
518 
519     char               *pszName;
520     char               *pszDBName;
521 
522     int                 bDSUpdate;
523     int                 bNoLogging;
524 
525     OGROCISession      *poSession;
526 
527     // We maintain a list of known SRID to reduce the number of trips to
528     // the database to get SRSes.
529     int                 nKnownSRID;
530     int                *panSRID;
531     OGRSpatialReference **papoSRS;
532 
533   public:
534                         OGROCIDataSource();
535                         virtual ~OGROCIDataSource();
536 
GetSession()537     OGROCISession      *GetSession() { return poSession; }
538 
539     int                 Open( const char *, char** papszOpenOptionsIn,
540                               int bUpdate, int bTestOpen );
541     int                 OpenTable( const char *pszTableName,
542                                    int nSRID, int bUpdate, int bTestOpen,
543                                    char** papszOpenOptionsIn );
544 
GetName()545     const char          *GetName() override { return pszName; }
GetLayerCount()546     int                 GetLayerCount() override { return nLayers; }
547     OGRLayer            *GetLayer( int ) override;
548     OGRLayer            *GetLayerByName(const char * pszName) override;
549 
550     virtual OGRErr      DeleteLayer(int) override;
551     virtual OGRLayer    *ICreateLayer( const char *,
552                                       OGRSpatialReference * = nullptr,
553                                       OGRwkbGeometryType = wkbUnknown,
554                                       char ** = nullptr ) override;
555 
556     int                 TestCapability( const char * ) override;
557 
558     void                DeleteLayer( const char * );
559 
560     void                TruncateLayer( const char * );
561     void                ValidateLayer( const char * );
562 
563     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
564                                     OGRGeometry *poSpatialFilter,
565                                     const char *pszDialect ) override;
566     virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
567 
568     int                 FetchSRSId( OGRSpatialReference * poSRS );
569     OGRSpatialReference *FetchSRS( int nSRID );
570 };
571 
572 /* -------------------------------------------------------------------- */
573 /*      Helper functions.                                               */
574 /* -------------------------------------------------------------------- */
575 int
576 OGROCIStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
577                                      double dfAlongX, double dfAlongY,
578                                      double dfEndX, double dfEndY,
579                                      double dfMaxAngleStepSizeDegrees,
580                                      int bForceWholeCircle,
581                                      OGRLineString *poLine );
582 
583 #endif /* ndef OGR_OCI_H_INCLUDED */
584