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