LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/hana - ogr_hana.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 33 35 94.3 %
Date: 2024-05-13 13:33:37 Functions: 14 15 93.3 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  SAP HANA Spatial Driver
       4             :  * Purpose:  SAP HANA Spatial OGR Driver Declarations.
       5             :  * Author:   Maxim Rylov
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2020, SAP SE
       9             :  *
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #ifndef OGR_HANA_H_INCLUDED
      30             : #define OGR_HANA_H_INCLUDED
      31             : 
      32             : #include "ogrsf_frmts.h"
      33             : #include "cpl_string.h"
      34             : 
      35             : #include <string>
      36             : #include <unordered_map>
      37             : #include <utility>
      38             : #include <vector>
      39             : 
      40             : #include "odbc/Forwards.h"
      41             : 
      42             : class OGRHanaDataSource;
      43             : 
      44             : namespace OGRHANA
      45             : {
      46             : 
      47             : constexpr static int DEFAULT_BATCH_SIZE = 4 * 1024 * 1024;
      48             : constexpr static int DEFAULT_STRING_SIZE = 256;
      49             : 
      50             : constexpr static int UNDETERMINED_SRID = -1;
      51             : 
      52             : /************************************************************************/
      53             : /*                          Internal struct definitions                 */
      54             : /************************************************************************/
      55             : 
      56             : struct ColumnDefinition
      57             : {
      58             :     CPLString name;
      59             :     CPLString typeDef;
      60             : };
      61             : 
      62             : struct AttributeColumnDescription
      63             : {
      64             :     CPLString name;
      65             :     short type = -1;
      66             :     CPLString typeName;
      67             :     int length = 0;  // the same type as in OGRFieldDefn.GetWidth
      68             :     unsigned short precision = 0;
      69             :     unsigned short scale = 0;
      70             :     bool isFeatureID = false;
      71             :     bool isArray = false;
      72             :     bool isAutoIncrement = false;
      73             :     bool isNullable = false;
      74             :     CPLString defaultValue;
      75             : };
      76             : 
      77             : struct GeometryColumnDescription
      78             : {
      79             :     CPLString name;
      80             :     OGRwkbGeometryType type;
      81             :     int srid;
      82             :     bool isNullable;
      83             : };
      84             : 
      85             : struct ColumnDescription
      86             : {
      87             :     bool isGeometry;
      88             :     AttributeColumnDescription attributeDescription;
      89             :     GeometryColumnDescription geometryDescription;
      90             : };
      91             : 
      92             : struct ColumnTypeInfo
      93             : {
      94             :     CPLString name;
      95             :     short type;
      96             :     int width;
      97             :     int precision;
      98             : };
      99             : 
     100             : struct Binary
     101             : {
     102             :     GByte *data;
     103             :     std::size_t size;
     104             : };
     105             : 
     106             : enum class BatchOperation
     107             : {
     108             :     NONE = 0,
     109             :     DELETE = 1,
     110             :     INSERT = 2,
     111             :     UPDATE = 4,
     112             :     ALL = 7
     113             : };
     114             : 
     115           8 : inline BatchOperation operator&(BatchOperation a, BatchOperation b)
     116             : {
     117             :     return static_cast<BatchOperation>(
     118             :         static_cast<std::underlying_type<BatchOperation>::type>(a) &
     119           8 :         static_cast<std::underlying_type<BatchOperation>::type>(b));
     120             : }
     121             : 
     122         141 : inline BatchOperation operator|(BatchOperation a, BatchOperation b)
     123             : {
     124             :     return static_cast<BatchOperation>(
     125             :         static_cast<std::underlying_type<BatchOperation>::type>(a) |
     126         141 :         static_cast<std::underlying_type<BatchOperation>::type>(b));
     127             : }
     128             : 
     129             : /************************************************************************/
     130             : /*                             OGRHanaLayer                             */
     131             : /************************************************************************/
     132             : 
     133             : class OGRHanaLayer : public OGRLayer
     134             : {
     135             :   protected:
     136             :     OGRHanaDataSource *dataSource_ = nullptr;
     137             :     OGRFeatureDefn *featureDefn_ = nullptr;
     138             :     GIntBig nextFeatureId_ = 0;
     139             :     std::vector<AttributeColumnDescription> attrColumns_;
     140             :     std::vector<GeometryColumnDescription> geomColumns_;
     141             :     int fidFieldIndex_ = OGRNullFID;
     142             :     CPLString fidFieldName_;
     143             :     CPLString rawQuery_;
     144             :     CPLString queryStatement_;
     145             :     CPLString whereClause_;
     146             :     CPLString attrFilter_;
     147             :     odbc::ResultSetRef resultSet_;
     148             :     std::vector<char> dataBuffer_;
     149             :     bool initialized_ = false;
     150             : 
     151             :     void EnsureInitialized();
     152             :     virtual OGRErr Initialize() = 0;
     153             : 
     154             :     void ClearQueryStatement();
     155             :     const CPLString &GetQueryStatement();
     156             :     void BuildWhereClause();
     157             :     void EnsureBufferCapacity(std::size_t size);
     158             :     virtual OGRFeature *GetNextFeatureInternal();
     159             :     int GetGeometryColumnSrid(int columnIndex) const;
     160             :     virtual OGRFeature *ReadFeature();
     161             :     OGRErr InitFeatureDefinition(const CPLString &schemaName,
     162             :                                  const CPLString &tableName,
     163             :                                  const CPLString &query,
     164             :                                  const CPLString &featureDefName);
     165             :     void ReadGeometryExtent(int geomField, OGREnvelope *extent);
     166             : 
     167             :   public:
     168             :     explicit OGRHanaLayer(OGRHanaDataSource *datasource);
     169             :     ~OGRHanaLayer() override;
     170             : 
     171           0 :     virtual bool IsTableLayer() const
     172             :     {
     173           0 :         return false;
     174             :     }
     175             : 
     176             :     void ResetReading() override;
     177             : 
     178           2 :     OGRErr GetExtent(OGREnvelope *extent, int force = TRUE) override
     179             :     {
     180           2 :         return GetExtent(0, extent, force);
     181             :     }
     182             : 
     183             :     OGRErr GetExtent(int geomField, OGREnvelope *extent, int force) override;
     184             :     GIntBig GetFeatureCount(int force) override;
     185             :     OGRFeature *GetNextFeature() override;
     186             :     const char *GetFIDColumn() override;
     187             :     OGRFeatureDefn *GetLayerDefn() override;
     188             :     const char *GetName() override;
     189             : 
     190             :     OGRErr SetAttributeFilter(const char *pszQuery) override;
     191             : 
     192          20 :     void SetSpatialFilter(OGRGeometry *poGeom) override
     193             :     {
     194          20 :         SetSpatialFilter(0, poGeom);
     195          20 :     }
     196             : 
     197             :     void SetSpatialFilter(int iGeomField, OGRGeometry *poGeom) override;
     198             : };
     199             : 
     200             : /************************************************************************/
     201             : /*                             OGRHanaTableLayer                        */
     202             : /************************************************************************/
     203             : 
     204             : class OGRHanaTableLayer final : public OGRHanaLayer
     205             : {
     206             :   private:
     207             :     CPLString schemaName_;
     208             :     CPLString tableName_;
     209             :     bool updateMode_ = false;
     210             : 
     211             :     odbc::PreparedStatementRef currentIdentityValueStmt_;
     212             :     odbc::PreparedStatementRef insertFeatureStmtWithFID_;
     213             :     odbc::PreparedStatementRef insertFeatureStmtWithoutFID_;
     214             :     odbc::PreparedStatementRef deleteFeatureStmt_;
     215             :     odbc::PreparedStatementRef updateFeatureStmt_;
     216             : 
     217             :     bool allowAutoFIDOnCreateFeature_ = false;
     218             :     std::size_t batchSize_ = DEFAULT_BATCH_SIZE;
     219             :     std::size_t defaultStringSize_ = DEFAULT_STRING_SIZE;
     220             :     bool launderColumnNames_ = true;
     221             :     bool preservePrecision_ = true;
     222             :     std::vector<ColumnDefinition> customColumnDefs_;
     223             :     bool parseFunctionsChecked_ = false;
     224             : 
     225             :     OGRErr Initialize() override;
     226             :     std::pair<OGRErr, std::size_t>
     227             :     ExecuteUpdate(odbc::PreparedStatement &statement, bool withBatch,
     228             :                   const char *functionName);
     229             :     odbc::PreparedStatementRef CreateDeleteFeatureStatement();
     230             :     odbc::PreparedStatementRef CreateInsertFeatureStatement(bool withFID);
     231             :     odbc::PreparedStatementRef CreateUpdateFeatureStatement();
     232             :     void ResetPreparedStatements();
     233             :     OGRErr SetStatementParameters(odbc::PreparedStatement &statement,
     234             :                                   OGRFeature *feature, bool newFeature,
     235             :                                   bool withFID, const char *functionName);
     236             : 
     237             :     OGRErr ExecutePendingBatches(BatchOperation op);
     238             :     bool HasPendingBatches() const;
     239             :     ColumnTypeInfo GetColumnTypeInfo(const OGRFieldDefn &field) const;
     240             :     OGRErr GetGeometryWkb(OGRFeature *feature, int fieldIndex, Binary &binary);
     241             :     void ClearBatches();
     242             :     void ColumnsChanged();
     243             : 
     244             :   public:
     245             :     OGRHanaTableLayer(OGRHanaDataSource *datasource, const char *schemaName,
     246             :                       const char *tableName, int update);
     247             :     ~OGRHanaTableLayer() override;
     248             : 
     249         119 :     bool IsTableLayer() const override
     250             :     {
     251         119 :         return true;
     252             :     }
     253             : 
     254             :     OGRErr DropTable();
     255             : 
     256             :     void ResetReading() override;
     257             : 
     258           2 :     OGRErr GetExtent(OGREnvelope *extent, int force = TRUE) override
     259             :     {
     260           2 :         return GetExtent(0, extent, force);
     261             :     }
     262             : 
     263             :     OGRErr GetExtent(int geomField, OGREnvelope *extent, int force) override;
     264             :     GIntBig GetFeatureCount(int force) override;
     265             : 
     266         523 :     const char *GetName() override
     267             :     {
     268         523 :         return tableName_.c_str();
     269             :     }
     270             : 
     271             :     int TestCapability(const char *capabilities) override;
     272             : 
     273             :     OGRErr ICreateFeature(OGRFeature *feature) override;
     274             :     OGRErr DeleteFeature(GIntBig nFID) override;
     275             :     OGRErr ISetFeature(OGRFeature *feature) override;
     276             : 
     277             :     OGRErr CreateField(const OGRFieldDefn *field, int approxOK = TRUE) override;
     278             :     OGRErr CreateGeomField(const OGRGeomFieldDefn *geomField,
     279             :                            int approxOK = TRUE) override;
     280             :     OGRErr DeleteField(int field) override;
     281             :     OGRErr AlterFieldDefn(int field, OGRFieldDefn *newFieldDefn,
     282             :                           int flagsIn) override;
     283             : 
     284          18 :     void SetBatchSize(std::size_t size)
     285             :     {
     286          18 :         batchSize_ = size;
     287          18 :     }
     288             : 
     289          18 :     void SetDefaultStringSize(std::size_t size)
     290             :     {
     291          18 :         defaultStringSize_ = size;
     292          18 :     }
     293             : 
     294          18 :     void SetLaunderFlag(bool flag)
     295             :     {
     296          18 :         launderColumnNames_ = flag;
     297          18 :     }
     298             : 
     299             :     void SetCustomColumnTypes(const char *columnTypes);
     300             : 
     301          18 :     void SetPrecisionFlag(bool flag)
     302             :     {
     303          18 :         preservePrecision_ = flag;
     304          18 :     }
     305             : 
     306             :     OGRErr StartTransaction() override;
     307             :     OGRErr CommitTransaction() override;
     308             :     OGRErr RollbackTransaction() override;
     309             : 
     310             :     void FlushPendingBatches(bool commit);
     311             : };
     312             : 
     313             : /************************************************************************/
     314             : /*                              OGRHanaResultLayer                      */
     315             : /************************************************************************/
     316             : 
     317             : class OGRHanaResultLayer final : public OGRHanaLayer
     318             : {
     319             :     OGRErr Initialize() override;
     320             : 
     321             :   public:
     322             :     explicit OGRHanaResultLayer(OGRHanaDataSource *datasource,
     323             :                                 const char *query);
     324             : 
     325             :     int TestCapability(const char *capabilities) override;
     326             : };
     327             : 
     328             : }  // namespace OGRHANA
     329             : 
     330             : /************************************************************************/
     331             : /*                          OGRHanaDataSource                          */
     332             : /************************************************************************/
     333             : 
     334             : class OGRHanaDataSource final : public GDALDataset
     335             : {
     336             :   private:
     337             :     friend class OGRHANA::OGRHanaLayer;
     338             :     friend class OGRHANA::OGRHanaTableLayer;
     339             :     friend class OGRHANA::OGRHanaResultLayer;
     340             : 
     341             :     using SrsCache = std::unordered_map<int, OGRSpatialReference *>;
     342             : 
     343             :     CPLString schemaName_;
     344             :     bool updateMode_ = false;
     345             :     bool detectGeometryType_ = true;
     346             :     bool isTransactionStarted_ = false;
     347             :     std::vector<std::unique_ptr<OGRLayer>> layers_;
     348             :     SrsCache srsCache_;
     349             :     odbc::EnvironmentRef connEnv_;
     350             :     odbc::ConnectionRef conn_;
     351             :     int majorVersion_ = 0;
     352             : 
     353             :   private:
     354             :     void CreateTable(const CPLString &tableName, const CPLString &fidName,
     355             :                      const CPLString &fidType, const CPLString &geomColumnName,
     356             :                      OGRwkbGeometryType geomType, bool geomColumnNullable,
     357             :                      const CPLString &geomColumnIndexType, int geomSrid);
     358             : 
     359             :   protected:
     360             :     std::pair<CPLString, CPLString> FindSchemaAndTableNames(const char *query);
     361             :     int FindLayerByName(const char *name);
     362             :     CPLString FindSchemaName(const char *objectName);
     363             : 
     364             :     odbc::StatementRef CreateStatement();
     365             :     odbc::PreparedStatementRef PrepareStatement(const char *sql);
     366             :     void Commit();
     367             :     void ExecuteSQL(const CPLString &sql);
     368             : 
     369             :     OGRSpatialReference *GetSrsById(int srid);
     370             :     int GetSrsId(const OGRSpatialReference *srs);
     371             :     bool IsSrsRoundEarth(int srid);
     372             :     bool HasSrsPlanarEquivalent(int srid);
     373             :     OGRErr GetQueryColumns(
     374             :         const CPLString &schemaName, const CPLString &query,
     375             :         std::vector<OGRHANA::ColumnDescription> &columnDescriptions);
     376             :     std::vector<CPLString> GetTablePrimaryKeys(const char *schemaName,
     377             :                                                const char *tableName);
     378             : 
     379             :     void InitializeLayers(const char *schemaName, const char *tableNames);
     380             :     void CreateSpatialReferenceSystem(const OGRSpatialReference &srs, int srid,
     381             :                                       const char *authorityName,
     382             :                                       int authorityCode, const CPLString &wkt,
     383             :                                       const CPLString &proj4);
     384             : 
     385             :     std::pair<OGRErr, CPLString> LaunderName(const char *name);
     386             : 
     387         366 :     bool IsTransactionStarted() const
     388             :     {
     389         366 :         return isTransactionStarted_;
     390             :     }
     391             : 
     392             :     void CreateParseArrayFunctions(const char *schemaName);
     393             :     bool ParseArrayFunctionsExist(const char *schemaName);
     394             : 
     395             :   public:
     396             :     static const char *GetPrefix();
     397             : 
     398             :   public:
     399             :     OGRHanaDataSource();
     400             :     ~OGRHanaDataSource() override;
     401             : 
     402             :     int Open(const char *newName, char **options, int update);
     403             : 
     404          24 :     int GetMajorVersion() const
     405             :     {
     406          24 :         return majorVersion_;
     407             :     }
     408             : 
     409             :     OGRErr DeleteLayer(int index) override;
     410             : 
     411           2 :     int GetLayerCount() override
     412             :     {
     413           2 :         return static_cast<int>(layers_.size());
     414             :     }
     415             : 
     416             :     OGRLayer *GetLayer(int index) override;
     417             :     OGRLayer *GetLayerByName(const char *) override;
     418             :     OGRLayer *ICreateLayer(const char *pszName,
     419             :                            const OGRGeomFieldDefn *poGeomFieldDefn,
     420             :                            CSLConstList papszOptions) override;
     421             :     int TestCapability(const char *capabilities) override;
     422             : 
     423             :     OGRLayer *ExecuteSQL(const char *sqlCommand, OGRGeometry *spatialFilter,
     424             :                          const char *dialect) override;
     425             : 
     426             :     OGRErr StartTransaction(int bForce = FALSE) override;
     427             :     OGRErr CommitTransaction() override;
     428             :     OGRErr RollbackTransaction() override;
     429             : };
     430             : 
     431             : #endif /* ndef OGR_HANA_H_INCLUDED */

Generated by: LCOV version 1.14