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: 28 30 93.3 %
Date: 2025-02-20 10:14:44 Functions: 12 13 92.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             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #ifndef OGR_HANA_H_INCLUDED
      14             : #define OGR_HANA_H_INCLUDED
      15             : 
      16             : #include "hana/ogrhanautils.h"
      17             : #include "ogrsf_frmts.h"
      18             : #include "cpl_string.h"
      19             : 
      20             : #include <string>
      21             : #include <unordered_map>
      22             : #include <utility>
      23             : #include <vector>
      24             : 
      25             : #include "odbc/Forwards.h"
      26             : #include "odbc/Types.h"
      27             : 
      28             : class OGRHanaDataSource;
      29             : 
      30             : namespace OGRHANA
      31             : {
      32             : 
      33             : constexpr static int DEFAULT_BATCH_SIZE = 4 * 1024 * 1024;
      34             : constexpr static int DEFAULT_STRING_SIZE = 256;
      35             : 
      36             : constexpr static int UNDETERMINED_SRID = -1;
      37             : 
      38             : /************************************************************************/
      39             : /*                 Internal enum and struct definitions                 */
      40             : /************************************************************************/
      41             : 
      42             : class QGRHanaDataTypes
      43             : {
      44             :     QGRHanaDataTypes() = delete;
      45             : 
      46             :   public:
      47             :     /// Unknown data type.
      48             :     static constexpr int Unknown = odbc::SQLDataTypes::Unknown;
      49             :     /// 64-bit integer value.
      50             :     static constexpr int BigInt = odbc::SQLDataTypes::BigInt;
      51             :     /// Binary data of fixed length.
      52             :     static constexpr int Binary = odbc::SQLDataTypes::Binary;
      53             :     /// Single bit binary data.
      54             :     static constexpr int Bit = odbc::SQLDataTypes::Bit;
      55             :     /// Boolean value.
      56             :     static constexpr int Boolean = odbc::SQLDataTypes::Boolean;
      57             :     /// Character string of fixed string length.
      58             :     static constexpr int Char = odbc::SQLDataTypes::Char;
      59             :     /// Year, month, and day fields.
      60             :     static constexpr int Date = odbc::SQLDataTypes::Date;
      61             :     /// Year, month, and day fields.
      62             :     static constexpr int DateTime = odbc::SQLDataTypes::DateTime;
      63             :     /// Signed, exact, numeric value.
      64             :     static constexpr int Decimal = odbc::SQLDataTypes::Decimal;
      65             :     /// Double-precision floating point number.
      66             :     static constexpr int Double = odbc::SQLDataTypes::Double;
      67             :     /// Floating point number with driver-specific precision.
      68             :     static constexpr int Float = odbc::SQLDataTypes::Float;
      69             :     /// 32-bit integer value.
      70             :     static constexpr int Integer = odbc::SQLDataTypes::Integer;
      71             :     /// Variable length binary data.
      72             :     static constexpr int LongVarBinary = odbc::SQLDataTypes::LongVarBinary;
      73             :     /// Variable length character data.
      74             :     static constexpr int LongVarChar = odbc::SQLDataTypes::LongVarChar;
      75             :     /// Signed, exact, numeric value.
      76             :     static constexpr int Numeric = odbc::SQLDataTypes::Numeric;
      77             :     /// Single-precision floating point number.
      78             :     static constexpr int Real = odbc::SQLDataTypes::Real;
      79             :     /// 16-bit integer value.
      80             :     static constexpr int SmallInt = odbc::SQLDataTypes::SmallInt;
      81             :     /// Hour, minute, and second fields.
      82             :     static constexpr int Time = odbc::SQLDataTypes::Time;
      83             :     /// Year, month, day, hour, minute, and second fields.
      84             :     static constexpr int Timestamp = odbc::SQLDataTypes::Timestamp;
      85             :     /// 8-bit integer value.
      86             :     static constexpr int TinyInt = odbc::SQLDataTypes::TinyInt;
      87             :     /// Year, month, and day fields.
      88             :     static constexpr int TypeDate = odbc::SQLDataTypes::TypeDate;
      89             :     /// Hour, minute, and second fields.
      90             :     static constexpr int TypeTime = odbc::SQLDataTypes::TypeTime;
      91             :     /// Year, month, day, hour, minute, and second fields.
      92             :     static constexpr int TypeTimestamp = odbc::SQLDataTypes::TypeTimestamp;
      93             :     /// Variable length binary data.
      94             :     static constexpr int VarBinary = odbc::SQLDataTypes::VarBinary;
      95             :     /// Variable-length character string.
      96             :     static constexpr int VarChar = odbc::SQLDataTypes::VarChar;
      97             :     /// Unicode character string of fixed string length.
      98             :     static constexpr int WChar = odbc::SQLDataTypes::WChar;
      99             :     /// Unicode variable-length character data.
     100             :     static constexpr int WLongVarChar = odbc::SQLDataTypes::WLongVarChar;
     101             :     /// Unicode variable-length character string.
     102             :     static constexpr int WVarChar = odbc::SQLDataTypes::WVarChar;
     103             :     /// ST_GEOMETRY/ST_POINT value.
     104             :     static constexpr int Geometry = 29812;
     105             :     /// REAL_VECTOR value.
     106             :     static constexpr int RealVector = 29814;
     107             : };
     108             : 
     109             : struct ColumnDefinition
     110             : {
     111             :     CPLString name;
     112             :     CPLString typeDef;
     113             : };
     114             : 
     115             : struct AttributeColumnDescription
     116             : {
     117             :     CPLString name;
     118             :     short type = -1;
     119             :     CPLString typeName;
     120             :     int length = 0;  // the same type as in OGRFieldDefn.GetWidth
     121             :     unsigned short precision = 0;
     122             :     unsigned short scale = 0;
     123             :     bool isFeatureID = false;
     124             :     bool isArray = false;
     125             :     bool isAutoIncrement = false;
     126             :     bool isNullable = false;
     127             :     CPLString defaultValue;
     128             : };
     129             : 
     130             : struct GeometryColumnDescription
     131             : {
     132             :     CPLString name;
     133             :     OGRwkbGeometryType type;
     134             :     int srid;
     135             :     bool isNullable;
     136             : };
     137             : 
     138             : struct ColumnDescription
     139             : {
     140             :     bool isGeometry;
     141             :     AttributeColumnDescription attributeDescription;
     142             :     GeometryColumnDescription geometryDescription;
     143             : };
     144             : 
     145             : struct ColumnTypeInfo
     146             : {
     147             :     CPLString name;
     148             :     short type;
     149             :     int width;
     150             :     int precision;
     151             : };
     152             : 
     153             : struct Binary
     154             : {
     155             :     GByte *data;
     156             :     std::size_t size;
     157             : };
     158             : 
     159             : enum class BatchOperation
     160             : {
     161             :     NONE = 0,
     162             :     DELETE = 1,
     163             :     INSERT = 2,
     164             :     UPDATE = 4,
     165             :     ALL = 7
     166             : };
     167             : 
     168           8 : inline BatchOperation operator&(BatchOperation a, BatchOperation b)
     169             : {
     170             :     return static_cast<BatchOperation>(
     171             :         static_cast<std::underlying_type<BatchOperation>::type>(a) &
     172           8 :         static_cast<std::underlying_type<BatchOperation>::type>(b));
     173             : }
     174             : 
     175         144 : inline BatchOperation operator|(BatchOperation a, BatchOperation b)
     176             : {
     177             :     return static_cast<BatchOperation>(
     178             :         static_cast<std::underlying_type<BatchOperation>::type>(a) |
     179         144 :         static_cast<std::underlying_type<BatchOperation>::type>(b));
     180             : }
     181             : 
     182             : /************************************************************************/
     183             : /*                             OGRHanaLayer                             */
     184             : /************************************************************************/
     185             : 
     186             : class OGRHanaLayer : public OGRLayer
     187             : {
     188             :   protected:
     189             :     OGRHanaDataSource *dataSource_ = nullptr;
     190             :     OGRFeatureDefn *featureDefn_ = nullptr;
     191             :     GIntBig nextFeatureId_ = 0;
     192             :     std::vector<AttributeColumnDescription> attrColumns_;
     193             :     std::vector<GeometryColumnDescription> geomColumns_;
     194             :     int fidFieldIndex_ = OGRNullFID;
     195             :     CPLString fidFieldName_;
     196             :     CPLString rawQuery_;
     197             :     CPLString queryStatement_;
     198             :     CPLString whereClause_;
     199             :     CPLString attrFilter_;
     200             :     odbc::ResultSetRef resultSet_;
     201             :     std::vector<char> dataBuffer_;
     202             :     bool initialized_ = false;
     203             : 
     204             :     void EnsureInitialized();
     205             :     virtual OGRErr Initialize() = 0;
     206             : 
     207             :     void ClearQueryStatement();
     208             :     const CPLString &GetQueryStatement();
     209             :     void BuildWhereClause();
     210             :     void EnsureBufferCapacity(std::size_t size);
     211             :     virtual OGRFeature *GetNextFeatureInternal();
     212             :     int GetGeometryColumnSrid(int columnIndex) const;
     213             :     virtual OGRFeature *ReadFeature();
     214             :     OGRErr InitFeatureDefinition(const CPLString &schemaName,
     215             :                                  const CPLString &tableName,
     216             :                                  const CPLString &query,
     217             :                                  const CPLString &featureDefName);
     218             :     void ReadGeometryExtent(int geomField, OGREnvelope *extent, int force);
     219             :     bool IsFastExtentAvailable();
     220             : 
     221             :   public:
     222             :     explicit OGRHanaLayer(OGRHanaDataSource *datasource);
     223             :     ~OGRHanaLayer() override;
     224             : 
     225           0 :     virtual bool IsTableLayer() const
     226             :     {
     227           0 :         return false;
     228             :     }
     229             : 
     230             :     void ResetReading() override;
     231             : 
     232             :     OGRErr IGetExtent(int geomField, OGREnvelope *extent, bool force) override;
     233             :     GIntBig GetFeatureCount(int force) override;
     234             :     OGRFeature *GetNextFeature() override;
     235             :     const char *GetFIDColumn() override;
     236             :     OGRFeatureDefn *GetLayerDefn() override;
     237             :     const char *GetName() override;
     238             : 
     239             :     OGRErr SetAttributeFilter(const char *pszQuery) override;
     240             : 
     241             :     OGRErr ISetSpatialFilter(int iGeomField,
     242             :                              const OGRGeometry *poGeom) override;
     243             : };
     244             : 
     245             : /************************************************************************/
     246             : /*                             OGRHanaTableLayer                        */
     247             : /************************************************************************/
     248             : 
     249             : class OGRHanaTableLayer final : public OGRHanaLayer
     250             : {
     251             :   private:
     252             :     CPLString schemaName_;
     253             :     CPLString tableName_;
     254             :     bool updateMode_ = false;
     255             : 
     256             :     odbc::PreparedStatementRef currentIdentityValueStmt_;
     257             :     odbc::PreparedStatementRef insertFeatureStmtWithFID_;
     258             :     odbc::PreparedStatementRef insertFeatureStmtWithoutFID_;
     259             :     odbc::PreparedStatementRef deleteFeatureStmt_;
     260             :     odbc::PreparedStatementRef updateFeatureStmt_;
     261             : 
     262             :     bool allowAutoFIDOnCreateFeature_ = false;
     263             :     std::size_t batchSize_ = DEFAULT_BATCH_SIZE;
     264             :     std::size_t defaultStringSize_ = DEFAULT_STRING_SIZE;
     265             :     bool launderColumnNames_ = true;
     266             :     bool preservePrecision_ = true;
     267             :     std::vector<ColumnDefinition> customColumnDefs_;
     268             :     bool parseFunctionsChecked_ = false;
     269             : 
     270             :     OGRErr Initialize() override;
     271             :     std::pair<OGRErr, std::size_t>
     272             :     ExecuteUpdate(odbc::PreparedStatement &statement, bool withBatch,
     273             :                   const char *functionName);
     274             :     odbc::PreparedStatementRef CreateDeleteFeatureStatement();
     275             :     odbc::PreparedStatementRef CreateInsertFeatureStatement(bool withFID);
     276             :     odbc::PreparedStatementRef CreateUpdateFeatureStatement();
     277             :     void ResetPreparedStatements();
     278             :     OGRErr SetStatementParameters(odbc::PreparedStatement &statement,
     279             :                                   OGRFeature *feature, bool newFeature,
     280             :                                   bool withFID, const char *functionName);
     281             : 
     282             :     OGRErr ExecutePendingBatches(BatchOperation op);
     283             :     bool HasPendingBatches() const;
     284             :     ColumnTypeInfo GetColumnTypeInfo(const OGRFieldDefn &field) const;
     285             :     OGRErr GetGeometryWkb(OGRFeature *feature, int fieldIndex, Binary &binary);
     286             :     void ClearBatches();
     287             :     void ColumnsChanged();
     288             : 
     289             :   public:
     290             :     OGRHanaTableLayer(OGRHanaDataSource *datasource, const char *schemaName,
     291             :                       const char *tableName, int update);
     292             :     ~OGRHanaTableLayer() override;
     293             : 
     294         121 :     bool IsTableLayer() const override
     295             :     {
     296         121 :         return true;
     297             :     }
     298             : 
     299             :     OGRErr DropTable();
     300             : 
     301             :     void ResetReading() override;
     302             : 
     303             :     OGRErr IGetExtent(int iGeomField, OGREnvelope *extent, bool force) override;
     304             : 
     305             :     GIntBig GetFeatureCount(int force) override;
     306             : 
     307         592 :     const char *GetName() override
     308             :     {
     309         592 :         return tableName_.c_str();
     310             :     }
     311             : 
     312             :     int TestCapability(const char *capabilities) override;
     313             : 
     314             :     OGRErr ICreateFeature(OGRFeature *feature) override;
     315             :     OGRErr DeleteFeature(GIntBig nFID) override;
     316             :     OGRErr ISetFeature(OGRFeature *feature) override;
     317             : 
     318             :     OGRErr CreateField(const OGRFieldDefn *field, int approxOK = TRUE) override;
     319             :     OGRErr CreateGeomField(const OGRGeomFieldDefn *geomField,
     320             :                            int approxOK = TRUE) override;
     321             :     OGRErr DeleteField(int field) override;
     322             :     OGRErr AlterFieldDefn(int field, OGRFieldDefn *newFieldDefn,
     323             :                           int flagsIn) override;
     324             : 
     325          18 :     void SetBatchSize(std::size_t size)
     326             :     {
     327          18 :         batchSize_ = size;
     328          18 :     }
     329             : 
     330          18 :     void SetDefaultStringSize(std::size_t size)
     331             :     {
     332          18 :         defaultStringSize_ = size;
     333          18 :     }
     334             : 
     335          18 :     void SetLaunderFlag(bool flag)
     336             :     {
     337          18 :         launderColumnNames_ = flag;
     338          18 :     }
     339             : 
     340             :     void SetCustomColumnTypes(const char *columnTypes);
     341             : 
     342          18 :     void SetPrecisionFlag(bool flag)
     343             :     {
     344          18 :         preservePrecision_ = flag;
     345          18 :     }
     346             : 
     347             :     OGRErr StartTransaction() override;
     348             :     OGRErr CommitTransaction() override;
     349             :     OGRErr RollbackTransaction() override;
     350             : 
     351             :     void FlushPendingBatches(bool commit);
     352             : };
     353             : 
     354             : /************************************************************************/
     355             : /*                              OGRHanaResultLayer                      */
     356             : /************************************************************************/
     357             : 
     358             : class OGRHanaResultLayer final : public OGRHanaLayer
     359             : {
     360             :     OGRErr Initialize() override;
     361             : 
     362             :   public:
     363             :     explicit OGRHanaResultLayer(OGRHanaDataSource *datasource,
     364             :                                 const char *query);
     365             : 
     366             :     int TestCapability(const char *capabilities) override;
     367             : };
     368             : 
     369             : }  // namespace OGRHANA
     370             : 
     371             : /************************************************************************/
     372             : /*                          OGRHanaDataSource                          */
     373             : /************************************************************************/
     374             : 
     375             : class OGRHanaDataSource final : public GDALDataset
     376             : {
     377             :   private:
     378             :     friend class OGRHANA::OGRHanaLayer;
     379             :     friend class OGRHANA::OGRHanaTableLayer;
     380             :     friend class OGRHANA::OGRHanaResultLayer;
     381             : 
     382             :     using SrsCache = std::unordered_map<int, OGRSpatialReference *>;
     383             : 
     384             :     CPLString schemaName_;
     385             :     bool updateMode_ = false;
     386             :     bool detectGeometryType_ = true;
     387             :     bool isTransactionStarted_ = false;
     388             :     std::vector<std::unique_ptr<OGRLayer>> layers_;
     389             :     SrsCache srsCache_;
     390             :     odbc::EnvironmentRef connEnv_;
     391             :     odbc::ConnectionRef conn_;
     392             :     OGRHANA::HanaVersion hanaVersion_;
     393             :     OGRHANA::HanaVersion cloudVersion_;
     394             : 
     395             :   private:
     396             :     void CreateTable(const CPLString &tableName, const CPLString &fidName,
     397             :                      const CPLString &fidType, const CPLString &geomColumnName,
     398             :                      OGRwkbGeometryType geomType, bool geomColumnNullable,
     399             :                      const CPLString &geomColumnIndexType, int geomSrid);
     400             :     void DetermineVersions();
     401             : 
     402             :   protected:
     403             :     std::pair<CPLString, CPLString> FindSchemaAndTableNames(const char *query);
     404             :     int FindLayerByName(const char *name);
     405             :     CPLString FindSchemaName(const char *objectName);
     406             : 
     407             :     odbc::StatementRef CreateStatement();
     408             :     odbc::PreparedStatementRef PrepareStatement(const char *sql);
     409             :     void Commit();
     410             :     void ExecuteSQL(const CPLString &sql);
     411             : 
     412             :     OGRSpatialReference *GetSrsById(int srid);
     413             :     int GetSrsId(const OGRSpatialReference *srs);
     414             :     bool IsSrsRoundEarth(int srid);
     415             :     bool HasSrsPlanarEquivalent(int srid);
     416             :     OGRErr GetQueryColumns(
     417             :         const CPLString &schemaName, const CPLString &query,
     418             :         std::vector<OGRHANA::ColumnDescription> &columnDescriptions);
     419             :     std::vector<CPLString> GetTablePrimaryKeys(const char *schemaName,
     420             :                                                const char *tableName);
     421             : 
     422             :     void InitializeLayers(const char *schemaName, const char *tableNames);
     423             :     void CreateSpatialReferenceSystem(const OGRSpatialReference &srs, int srid,
     424             :                                       const char *authorityName,
     425             :                                       int authorityCode, const CPLString &wkt,
     426             :                                       const CPLString &proj4);
     427             : 
     428             :     std::pair<OGRErr, CPLString> LaunderName(const char *name);
     429             : 
     430         372 :     bool IsTransactionStarted() const
     431             :     {
     432         372 :         return isTransactionStarted_;
     433             :     }
     434             : 
     435             :     void CreateParseArrayFunctions(const char *schemaName);
     436             :     bool ParseArrayFunctionsExist(const char *schemaName);
     437             : 
     438             :   public:
     439             :     static const char *GetPrefix();
     440             : 
     441             :   public:
     442             :     OGRHanaDataSource();
     443             :     ~OGRHanaDataSource() override;
     444             : 
     445             :     int Open(const char *newName, char **options, int update);
     446             : 
     447          40 :     OGRHANA::HanaVersion GetHanaVersion() const
     448             :     {
     449          40 :         return hanaVersion_;
     450             :     }
     451             : 
     452          16 :     OGRHANA::HanaVersion GetHanaCloudVersion() const
     453             :     {
     454          16 :         return cloudVersion_;
     455             :     }
     456             : 
     457             :     OGRErr DeleteLayer(int index) override;
     458             : 
     459           2 :     int GetLayerCount() override
     460             :     {
     461           2 :         return static_cast<int>(layers_.size());
     462             :     }
     463             : 
     464             :     OGRLayer *GetLayer(int index) override;
     465             :     OGRLayer *GetLayerByName(const char *) override;
     466             :     OGRLayer *ICreateLayer(const char *pszName,
     467             :                            const OGRGeomFieldDefn *poGeomFieldDefn,
     468             :                            CSLConstList papszOptions) override;
     469             :     int TestCapability(const char *capabilities) override;
     470             : 
     471             :     OGRLayer *ExecuteSQL(const char *sqlCommand, OGRGeometry *spatialFilter,
     472             :                          const char *dialect) override;
     473             : 
     474             :     OGRErr StartTransaction(int bForce = FALSE) override;
     475             :     OGRErr CommitTransaction() override;
     476             :     OGRErr RollbackTransaction() override;
     477             : };
     478             : 
     479             : #endif /* ndef OGR_HANA_H_INCLUDED */

Generated by: LCOV version 1.14