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-09-10 17:48:50 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() const;
     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() const override;
     236             :     using OGRLayer::GetLayerDefn;
     237             :     const OGRFeatureDefn *GetLayerDefn() const override;
     238             :     const char *GetName() const override;
     239             : 
     240             :     OGRErr SetAttributeFilter(const char *pszQuery) override;
     241             : 
     242             :     OGRErr ISetSpatialFilter(int iGeomField,
     243             :                              const OGRGeometry *poGeom) override;
     244             : };
     245             : 
     246             : /************************************************************************/
     247             : /*                             OGRHanaTableLayer                        */
     248             : /************************************************************************/
     249             : 
     250             : class OGRHanaTableLayer final : public OGRHanaLayer
     251             : {
     252             :   private:
     253             :     CPLString schemaName_;
     254             :     CPLString tableName_;
     255             :     bool updateMode_ = false;
     256             : 
     257             :     odbc::PreparedStatementRef currentIdentityValueStmt_;
     258             :     odbc::PreparedStatementRef insertFeatureStmtWithFID_;
     259             :     odbc::PreparedStatementRef insertFeatureStmtWithoutFID_;
     260             :     odbc::PreparedStatementRef deleteFeatureStmt_;
     261             :     odbc::PreparedStatementRef updateFeatureStmt_;
     262             : 
     263             :     bool allowAutoFIDOnCreateFeature_ = false;
     264             :     std::size_t batchSize_ = DEFAULT_BATCH_SIZE;
     265             :     std::size_t defaultStringSize_ = DEFAULT_STRING_SIZE;
     266             :     bool launderColumnNames_ = true;
     267             :     bool preservePrecision_ = true;
     268             :     std::vector<ColumnDefinition> customColumnDefs_;
     269             :     bool parseFunctionsChecked_ = false;
     270             : 
     271             :     OGRErr Initialize() override;
     272             :     std::pair<OGRErr, std::size_t>
     273             :     ExecuteUpdate(odbc::PreparedStatement &statement, bool withBatch,
     274             :                   const char *functionName);
     275             :     odbc::PreparedStatementRef CreateDeleteFeatureStatement();
     276             :     odbc::PreparedStatementRef CreateInsertFeatureStatement(bool withFID);
     277             :     odbc::PreparedStatementRef CreateUpdateFeatureStatement();
     278             :     void ResetPreparedStatements();
     279             :     OGRErr SetStatementParameters(odbc::PreparedStatement &statement,
     280             :                                   OGRFeature *feature, bool newFeature,
     281             :                                   bool withFID, const char *functionName);
     282             : 
     283             :     OGRErr ExecutePendingBatches(BatchOperation op);
     284             :     bool HasPendingBatches() const;
     285             :     ColumnTypeInfo GetColumnTypeInfo(const OGRFieldDefn &field) const;
     286             :     OGRErr GetGeometryWkb(OGRFeature *feature, int fieldIndex, Binary &binary);
     287             :     void ClearBatches();
     288             :     void ColumnsChanged();
     289             : 
     290             :   public:
     291             :     OGRHanaTableLayer(OGRHanaDataSource *datasource, const char *schemaName,
     292             :                       const char *tableName, int update);
     293             :     ~OGRHanaTableLayer() override;
     294             : 
     295         121 :     bool IsTableLayer() const override
     296             :     {
     297         121 :         return true;
     298             :     }
     299             : 
     300             :     OGRErr DropTable();
     301             : 
     302             :     void ResetReading() override;
     303             : 
     304             :     OGRErr IGetExtent(int iGeomField, OGREnvelope *extent, bool force) override;
     305             : 
     306             :     GIntBig GetFeatureCount(int force) override;
     307             : 
     308         592 :     const char *GetName() const override
     309             :     {
     310         592 :         return tableName_.c_str();
     311             :     }
     312             : 
     313             :     int TestCapability(const char *capabilities) const override;
     314             : 
     315             :     OGRErr ICreateFeature(OGRFeature *feature) override;
     316             :     OGRErr DeleteFeature(GIntBig nFID) override;
     317             :     OGRErr ISetFeature(OGRFeature *feature) override;
     318             : 
     319             :     OGRErr CreateField(const OGRFieldDefn *field, int approxOK = TRUE) override;
     320             :     OGRErr CreateGeomField(const OGRGeomFieldDefn *geomField,
     321             :                            int approxOK = TRUE) override;
     322             :     OGRErr DeleteField(int field) override;
     323             :     OGRErr AlterFieldDefn(int field, OGRFieldDefn *newFieldDefn,
     324             :                           int flagsIn) override;
     325             : 
     326          18 :     void SetBatchSize(std::size_t size)
     327             :     {
     328          18 :         batchSize_ = size;
     329          18 :     }
     330             : 
     331          18 :     void SetDefaultStringSize(std::size_t size)
     332             :     {
     333          18 :         defaultStringSize_ = size;
     334          18 :     }
     335             : 
     336          18 :     void SetLaunderFlag(bool flag)
     337             :     {
     338          18 :         launderColumnNames_ = flag;
     339          18 :     }
     340             : 
     341             :     void SetCustomColumnTypes(const char *columnTypes);
     342             : 
     343          18 :     void SetPrecisionFlag(bool flag)
     344             :     {
     345          18 :         preservePrecision_ = flag;
     346          18 :     }
     347             : 
     348             :     OGRErr StartTransaction() override;
     349             :     OGRErr CommitTransaction() override;
     350             :     OGRErr RollbackTransaction() override;
     351             : 
     352             :     void FlushPendingBatches(bool commit);
     353             : };
     354             : 
     355             : /************************************************************************/
     356             : /*                              OGRHanaResultLayer                      */
     357             : /************************************************************************/
     358             : 
     359             : class OGRHanaResultLayer final : public OGRHanaLayer
     360             : {
     361             :     OGRErr Initialize() override;
     362             : 
     363             :   public:
     364             :     explicit OGRHanaResultLayer(OGRHanaDataSource *datasource,
     365             :                                 const char *query);
     366             : 
     367             :     int TestCapability(const char *capabilities) const override;
     368             : };
     369             : 
     370             : }  // namespace OGRHANA
     371             : 
     372             : /************************************************************************/
     373             : /*                          OGRHanaDataSource                          */
     374             : /************************************************************************/
     375             : 
     376             : class OGRHanaDataSource final : public GDALDataset
     377             : {
     378             :   private:
     379             :     friend class OGRHANA::OGRHanaLayer;
     380             :     friend class OGRHANA::OGRHanaTableLayer;
     381             :     friend class OGRHANA::OGRHanaResultLayer;
     382             : 
     383             :     using SrsCache = std::unordered_map<int, OGRSpatialReference *>;
     384             : 
     385             :     CPLString schemaName_;
     386             :     bool updateMode_ = false;
     387             :     bool detectGeometryType_ = true;
     388             :     bool isTransactionStarted_ = false;
     389             :     std::vector<std::unique_ptr<OGRLayer>> layers_;
     390             :     SrsCache srsCache_;
     391             :     odbc::EnvironmentRef connEnv_;
     392             :     odbc::ConnectionRef conn_;
     393             :     OGRHANA::HanaVersion hanaVersion_;
     394             :     OGRHANA::HanaVersion cloudVersion_;
     395             : 
     396             :   private:
     397             :     void CreateTable(const CPLString &tableName, const CPLString &fidName,
     398             :                      const CPLString &fidType, const CPLString &geomColumnName,
     399             :                      OGRwkbGeometryType geomType, bool geomColumnNullable,
     400             :                      const CPLString &geomColumnIndexType, int geomSrid);
     401             :     void DetermineVersions();
     402             : 
     403             :   protected:
     404             :     std::pair<CPLString, CPLString> FindSchemaAndTableNames(const char *query);
     405             :     int FindLayerByName(const char *name);
     406             :     CPLString FindSchemaName(const char *objectName);
     407             : 
     408             :     odbc::StatementRef CreateStatement();
     409             :     odbc::PreparedStatementRef PrepareStatement(const char *sql);
     410             :     void Commit();
     411             :     void ExecuteSQL(const CPLString &sql);
     412             : 
     413             :     OGRSpatialReference *GetSrsById(int srid);
     414             :     int GetSrsId(const OGRSpatialReference *srs);
     415             :     bool IsSrsRoundEarth(int srid);
     416             :     bool HasSrsPlanarEquivalent(int srid);
     417             :     OGRErr GetQueryColumns(
     418             :         const CPLString &schemaName, const CPLString &query,
     419             :         std::vector<OGRHANA::ColumnDescription> &columnDescriptions);
     420             :     std::vector<CPLString> GetTablePrimaryKeys(const char *schemaName,
     421             :                                                const char *tableName);
     422             : 
     423             :     void InitializeLayers(const char *schemaName, const char *tableNames);
     424             :     void CreateSpatialReferenceSystem(const OGRSpatialReference &srs, int srid,
     425             :                                       const char *authorityName,
     426             :                                       int authorityCode, const CPLString &wkt,
     427             :                                       const CPLString &proj4);
     428             : 
     429             :     std::pair<OGRErr, CPLString> LaunderName(const char *name);
     430             : 
     431         372 :     bool IsTransactionStarted() const
     432             :     {
     433         372 :         return isTransactionStarted_;
     434             :     }
     435             : 
     436             :     void CreateParseArrayFunctions(const char *schemaName);
     437             :     bool ParseArrayFunctionsExist(const char *schemaName);
     438             : 
     439             :   public:
     440             :     static const char *GetPrefix();
     441             : 
     442             :   public:
     443             :     OGRHanaDataSource();
     444             :     ~OGRHanaDataSource() override;
     445             : 
     446             :     int Open(const char *newName, char **options, int update);
     447             : 
     448          40 :     OGRHANA::HanaVersion GetHanaVersion() const
     449             :     {
     450          40 :         return hanaVersion_;
     451             :     }
     452             : 
     453          16 :     OGRHANA::HanaVersion GetHanaCloudVersion() const
     454             :     {
     455          16 :         return cloudVersion_;
     456             :     }
     457             : 
     458             :     OGRErr DeleteLayer(int index) override;
     459             : 
     460           2 :     int GetLayerCount() const override
     461             :     {
     462           2 :         return static_cast<int>(layers_.size());
     463             :     }
     464             : 
     465             :     using GDALDataset::GetLayer;
     466             :     const OGRLayer *GetLayer(int index) const override;
     467             :     OGRLayer *GetLayerByName(const char *) override;
     468             :     OGRLayer *ICreateLayer(const char *pszName,
     469             :                            const OGRGeomFieldDefn *poGeomFieldDefn,
     470             :                            CSLConstList papszOptions) override;
     471             :     int TestCapability(const char *capabilities) const override;
     472             : 
     473             :     OGRLayer *ExecuteSQL(const char *sqlCommand, OGRGeometry *spatialFilter,
     474             :                          const char *dialect) override;
     475             : 
     476             :     OGRErr StartTransaction(int bForce = FALSE) override;
     477             :     OGRErr CommitTransaction() override;
     478             :     OGRErr RollbackTransaction() override;
     479             : };
     480             : 
     481             : #endif /* ndef OGR_HANA_H_INCLUDED */

Generated by: LCOV version 1.14