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 */
|