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