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