Line data Source code
1 : /******************************************************************************
2 : * $Id$
3 : *
4 : * Project: Elasticsearch Translator
5 : * Purpose:
6 : * Author:
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2011, Adam Estrada
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #ifndef OGR_ELASTIC_H_INCLUDED
15 : #define OGR_ELASTIC_H_INCLUDED
16 :
17 : #include "ogrsf_frmts.h"
18 :
19 : #include "cpl_json_header.h"
20 : #include "cpl_hash_set.h"
21 : #include "ogr_p.h"
22 : #include "cpl_http.h"
23 : #include "cpl_json.h"
24 :
25 : #include <map>
26 : #include <memory>
27 : #include <set>
28 : #include <vector>
29 :
30 : typedef enum
31 : {
32 : ES_GEOMTYPE_AUTO,
33 : ES_GEOMTYPE_GEO_POINT,
34 : ES_GEOMTYPE_GEO_SHAPE
35 : } ESGeometryTypeMapping;
36 :
37 : class OGRElasticDataSource;
38 :
39 : class OGRESSortDesc
40 : {
41 : public:
42 : CPLString osColumn;
43 : bool bAsc;
44 :
45 5 : OGRESSortDesc(const CPLString &osColumnIn, bool bAscIn)
46 5 : : osColumn(osColumnIn), bAsc(bAscIn)
47 : {
48 5 : }
49 : };
50 :
51 : /************************************************************************/
52 : /* OGRElasticLayer */
53 : /************************************************************************/
54 :
55 : class OGRElasticLayer final : public OGRLayer
56 : {
57 : OGRElasticDataSource *m_poDS = nullptr;
58 :
59 : CPLString m_osIndexName{};
60 : CPLString m_osMappingName{};
61 :
62 : OGRFeatureDefn *m_poFeatureDefn = nullptr;
63 : bool m_bFeatureDefnFinalized = false;
64 : bool m_bAddSourceIndexName = false;
65 :
66 : bool m_bManualMapping = false;
67 : bool m_bSerializeMapping = false;
68 : CPLString m_osWriteMapFilename{};
69 : bool m_bStoreFields = false;
70 : char **m_papszStoredFields = nullptr;
71 : char **m_papszNotAnalyzedFields = nullptr;
72 : char **m_papszNotIndexedFields = nullptr;
73 : char **m_papszFieldsWithRawValue = nullptr;
74 :
75 : CPLString m_osESSearch{};
76 : std::vector<OGRESSortDesc> m_aoSortColumns{};
77 :
78 : CPLString m_osBulkContent{};
79 : int m_nBulkUpload{};
80 :
81 : CPLString m_osFID{};
82 :
83 : std::vector<std::vector<CPLString>> m_aaosFieldPaths{};
84 : std::map<CPLString, int> m_aosMapToFieldIndex{};
85 :
86 : std::vector<std::vector<CPLString>> m_aaosGeomFieldPaths{};
87 : std::map<CPLString, int> m_aosMapToGeomFieldIndex{};
88 : std::vector<OGRCoordinateTransformation *> m_apoCT{};
89 : std::vector<int> m_abIsGeoPoint{};
90 : ESGeometryTypeMapping m_eGeomTypeMapping = ES_GEOMTYPE_AUTO;
91 : CPLString m_osPrecision{};
92 :
93 : CPLString m_osScrollID{};
94 : GIntBig m_iCurID = 0;
95 : GIntBig m_nNextFID = -1; // for creation
96 : int m_iCurFeatureInPage = 0;
97 : std::vector<OGRFeature *> m_apoCachedFeatures{};
98 : bool m_bEOF = false;
99 :
100 : json_object *m_poSpatialFilter = nullptr;
101 : CPLString m_osJSONFilter{};
102 : bool m_bFilterMustBeClientSideEvaluated = false;
103 : json_object *m_poJSONFilter = nullptr;
104 :
105 : bool m_bIgnoreSourceID = false;
106 : bool m_bDotAsNestedField = true;
107 :
108 : bool m_bAddPretty = false;
109 : bool m_bGeoShapeAsGeoJSON = false;
110 :
111 : CPLString m_osSingleQueryTimeout{};
112 : double m_dfSingleQueryTimeout = 0;
113 : double m_dfFeatureIterationTimeout = 0;
114 : //! Timestamp after which the query must be terminated
115 : double m_dfEndTimeStamp = 0;
116 :
117 : GIntBig m_nReadFeaturesSinceResetReading = 0;
118 : GIntBig m_nSingleQueryTerminateAfter = 0;
119 : GIntBig m_nFeatureIterationTerminateAfter = 0;
120 : CPLString m_osSingleQueryTerminateAfter;
121 :
122 : bool m_bUseSingleQueryParams = false;
123 :
124 : void CopyMembersTo(OGRElasticLayer *poNew);
125 :
126 : bool PushIndex();
127 : CPLString BuildMap();
128 :
129 : OGRErr WriteMapIfNecessary();
130 : OGRFeature *GetNextRawFeature();
131 : void BuildFeature(OGRFeature *poFeature, json_object *poSource,
132 : CPLString osPath);
133 : void CreateFieldFromSchema(const char *pszName, const char *pszPrefix,
134 : std::vector<CPLString> aosPath,
135 : json_object *poObj);
136 : void AddOrUpdateField(const char *pszAttrName, const char *pszKey,
137 : json_object *poObj, char chNestedAttributeSeparator,
138 : std::vector<CPLString> &aosPath);
139 :
140 : CPLString BuildMappingURL(bool bMappingApi);
141 :
142 : CPLString BuildJSonFromFeature(OGRFeature *poFeature);
143 :
144 : static CPLString BuildPathFromArray(const std::vector<CPLString> &aosPath);
145 :
146 : void AddFieldDefn(const char *pszName, OGRFieldType eType,
147 : const std::vector<CPLString> &aosPath,
148 : OGRFieldSubType eSubType = OFSTNone);
149 : void AddGeomFieldDefn(const char *pszName, OGRwkbGeometryType eType,
150 : const std::vector<CPLString> &aosPath,
151 : int bIsGeoPoint);
152 :
153 : CPLString BuildQuery(bool bCountOnly);
154 : json_object *GetValue(int nFieldIdx, swq_expr_node *poValNode);
155 : json_object *TranslateSQLToFilter(swq_expr_node *poNode);
156 : json_object *BuildSort();
157 :
158 : void AddTimeoutTerminateAfterToURL(CPLString &osURL);
159 :
160 : public:
161 : OGRElasticLayer(const char *pszLayerName, const char *pszIndexName,
162 : const char *pszMappingName, OGRElasticDataSource *poDS,
163 : CSLConstList papszOptions,
164 : const char *pszESSearch = nullptr);
165 : OGRElasticLayer(const char *pszLayerName,
166 : OGRElasticLayer *poReferenceLayer);
167 : virtual ~OGRElasticLayer();
168 :
169 : virtual void ResetReading() override;
170 : virtual OGRFeature *GetNextFeature() override;
171 :
172 : virtual OGRErr ICreateFeature(OGRFeature *poFeature) override;
173 : virtual OGRErr ISetFeature(OGRFeature *poFeature) override;
174 : OGRErr IUpsertFeature(OGRFeature *poFeature) override;
175 : virtual OGRErr CreateField(const OGRFieldDefn *poField,
176 : int bApproxOK) override;
177 : virtual OGRErr CreateGeomField(const OGRGeomFieldDefn *poField,
178 : int bApproxOK) override;
179 :
180 45 : virtual const char *GetName() override
181 : {
182 45 : return m_poFeatureDefn->GetName();
183 : }
184 :
185 : virtual OGRFeatureDefn *GetLayerDefn() override;
186 : virtual const char *GetFIDColumn() override;
187 :
188 : virtual int TestCapability(const char *) override;
189 :
190 : virtual GIntBig GetFeatureCount(int bForce) override;
191 :
192 9 : virtual void SetSpatialFilter(OGRGeometry *poGeom) override
193 : {
194 9 : SetSpatialFilter(0, poGeom);
195 9 : }
196 :
197 : virtual void SetSpatialFilter(int iGeomField, OGRGeometry *poGeom) override;
198 : virtual OGRErr SetAttributeFilter(const char *pszFilter) override;
199 :
200 0 : virtual OGRErr GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override
201 : {
202 0 : return GetExtent(0, psExtent, bForce);
203 : }
204 :
205 : virtual OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent,
206 : int bForce = TRUE) override;
207 :
208 : virtual OGRErr SyncToDisk() override;
209 :
210 : GDALDataset *GetDataset() override;
211 :
212 : void FinalizeFeatureDefn(bool bReadFeatures = true);
213 : void InitFeatureDefnFromMapping(json_object *poSchema,
214 : const char *pszPrefix,
215 : const std::vector<CPLString> &aosPath);
216 :
217 7 : const CPLString &GetIndexName() const
218 : {
219 7 : return m_osIndexName;
220 : }
221 :
222 1 : const CPLString &GetMappingName() const
223 : {
224 1 : return m_osMappingName;
225 : }
226 :
227 21 : void SetIgnoreSourceID(bool bFlag)
228 : {
229 21 : m_bIgnoreSourceID = bFlag;
230 21 : }
231 :
232 6 : void SetManualMapping()
233 : {
234 6 : m_bManualMapping = true;
235 6 : }
236 :
237 21 : void SetDotAsNestedField(bool bFlag)
238 : {
239 21 : m_bDotAsNestedField = bFlag;
240 21 : }
241 :
242 21 : void SetFID(const CPLString &m_osFIDIn)
243 : {
244 21 : m_osFID = m_osFIDIn;
245 21 : }
246 :
247 21 : void SetNextFID(GIntBig nNextFID)
248 : {
249 21 : m_nNextFID = nNextFID;
250 21 : }
251 :
252 : OGRElasticLayer *Clone();
253 :
254 3 : void SetOrderBy(const std::vector<OGRESSortDesc> &v)
255 : {
256 3 : m_aoSortColumns = v;
257 3 : }
258 :
259 3 : void SetFeatureDefnFinalized()
260 : {
261 3 : m_bFeatureDefnFinalized = true;
262 3 : }
263 :
264 : void GetGeomFieldProperties(int iGeomField, std::vector<CPLString> &aosPath,
265 : bool &bIsGeoPoint);
266 :
267 : static void ClampEnvelope(OGREnvelope &sEnvelope);
268 : };
269 :
270 : /************************************************************************/
271 : /* OGRElasticAggregationLayer */
272 : /************************************************************************/
273 :
274 : class OGRElasticAggregationLayer final
275 : : public OGRLayer,
276 : public OGRGetNextFeatureThroughRaw<OGRElasticAggregationLayer>
277 : {
278 :
279 : OGRElasticDataSource *m_poDS = nullptr;
280 : std::string m_osIndexName{};
281 : std::string m_osGeometryField{};
282 : OGRFeatureDefn *m_poFeatureDefn = nullptr;
283 : bool m_bFeaturesRequested = false;
284 : int m_iCurFeature = 0;
285 : bool m_bRequestHasSpatialFilter = false;
286 : int m_nGeohashGridMaxSize = 10000;
287 : int m_nGeohashGridPrecision = -1;
288 : CPLJSONObject m_oFieldDef{};
289 : CPLJSONObject m_oAggregatedFieldsRequest{};
290 : std::vector<std::unique_ptr<OGRFeature>> m_apoCachedFeatures{};
291 :
292 : explicit OGRElasticAggregationLayer(OGRElasticDataSource *poDS);
293 : std::string BuildRequest();
294 : void IssueAggregationRequest();
295 : OGRFeature *GetNextRawFeature();
296 :
297 : public:
298 : ~OGRElasticAggregationLayer() override;
299 :
300 3 : OGRFeatureDefn *GetLayerDefn() override
301 : {
302 3 : return m_poFeatureDefn;
303 : }
304 :
305 : void ResetReading() override;
306 7 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(OGRElasticAggregationLayer)
307 : GIntBig GetFeatureCount(int bForce) override;
308 : int TestCapability(const char *) override;
309 :
310 : using OGRLayer::SetSpatialFilter;
311 : void SetSpatialFilter(OGRGeometry *poGeom) override;
312 :
313 : GDALDataset *GetDataset() override;
314 :
315 : static std::unique_ptr<OGRElasticAggregationLayer>
316 : Build(OGRElasticDataSource *poDS, const char *pszAggregation);
317 : };
318 :
319 : /************************************************************************/
320 : /* OGRElasticDataSource */
321 : /************************************************************************/
322 :
323 : class OGRElasticDataSource final : public GDALDataset
324 : {
325 : char *m_pszName;
326 : CPLString m_osURL;
327 : CPLString m_osUserPwd;
328 : CPLString m_osFID;
329 :
330 : std::set<CPLString> m_oSetLayers;
331 : std::vector<std::unique_ptr<OGRElasticLayer>> m_apoLayers;
332 : std::unique_ptr<OGRElasticAggregationLayer> m_poAggregationLayer{};
333 : bool m_bAllLayersListed = false;
334 : std::map<OGRLayer *, OGRLayer *> m_oMapResultSet;
335 : std::map<std::string, std::string> m_oMapHeadersFromEnv{};
336 :
337 : bool CheckVersion();
338 : int GetLayerIndex(const char *pszName);
339 : void FetchMapping(const char *pszIndexName);
340 : bool OpenAggregation(const char *pszAggregation);
341 : std::vector<std::string> GetIndexList(const char *pszQueriedIndexName);
342 :
343 : public:
344 : OGRElasticDataSource();
345 : virtual ~OGRElasticDataSource();
346 :
347 : bool m_bOverwrite;
348 : int m_nBulkUpload;
349 : char *m_pszWriteMap;
350 : char *m_pszMapping;
351 : int m_nBatchSize;
352 : int m_nFeatureCountToEstablishFeatureDefn;
353 : bool m_bJSonField;
354 : bool m_bFlattenNestedAttributes;
355 : bool m_bAddSourceIndexName = false; // Only used for wildcard layers
356 : int m_nMajorVersion = 0;
357 : int m_nMinorVersion = 0;
358 :
359 : bool Open(GDALOpenInfo *poOpenInfo);
360 :
361 : int Create(const char *pszFilename, char **papszOptions);
362 :
363 : CPLHTTPResult *HTTPFetch(const char *pszURL, CSLConstList papszOptions);
364 :
365 237 : const char *GetURL()
366 : {
367 237 : return m_osURL.c_str();
368 : }
369 :
370 0 : virtual const char *GetName()
371 : {
372 0 : return m_pszName;
373 : }
374 :
375 : virtual int GetLayerCount() override;
376 : virtual OGRLayer *GetLayer(int) override;
377 : virtual OGRLayer *GetLayerByName(const char *pszName) override;
378 :
379 : OGRLayer *ICreateLayer(const char *pszName,
380 : const OGRGeomFieldDefn *poGeomFieldDefn,
381 : CSLConstList papszOptions) override;
382 : virtual OGRErr DeleteLayer(int iLayer) override;
383 :
384 : virtual OGRLayer *ExecuteSQL(const char *pszSQLCommand,
385 : OGRGeometry *poSpatialFilter,
386 : const char *pszDialect) override;
387 : virtual void ReleaseResultSet(OGRLayer *poLayer) override;
388 :
389 : virtual int TestCapability(const char *) override;
390 :
391 : bool UploadFile(const CPLString &url, const CPLString &data,
392 : const CPLString &osVerb = CPLString());
393 : void Delete(const CPLString &url);
394 :
395 : json_object *RunRequest(
396 : const char *pszURL, const char *pszPostContent = nullptr,
397 : const std::vector<int> &anSilentedHTTPErrors = std::vector<int>());
398 :
399 90 : const CPLString &GetFID() const
400 : {
401 90 : return m_osFID;
402 : }
403 :
404 : void FetchMapping(const char *pszIndexName, std::set<CPLString> &oSetLayers,
405 : std::vector<std::unique_ptr<OGRElasticLayer>> &apoLayers);
406 : };
407 :
408 : #endif /* ndef _OGR_Elastic_H_INCLUDED */
|