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 : OGRErr ISetSpatialFilter(int iGeomField,
192 : const OGRGeometry *poGeom) override;
193 :
194 : virtual OGRErr SetAttributeFilter(const char *pszFilter) override;
195 :
196 : virtual OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
197 : bool bForce) override;
198 :
199 : virtual OGRErr SyncToDisk() override;
200 :
201 : GDALDataset *GetDataset() override;
202 :
203 : void FinalizeFeatureDefn(bool bReadFeatures = true);
204 : void InitFeatureDefnFromMapping(json_object *poSchema,
205 : const char *pszPrefix,
206 : const std::vector<CPLString> &aosPath);
207 :
208 7 : const CPLString &GetIndexName() const
209 : {
210 7 : return m_osIndexName;
211 : }
212 :
213 1 : const CPLString &GetMappingName() const
214 : {
215 1 : return m_osMappingName;
216 : }
217 :
218 21 : void SetIgnoreSourceID(bool bFlag)
219 : {
220 21 : m_bIgnoreSourceID = bFlag;
221 21 : }
222 :
223 6 : void SetManualMapping()
224 : {
225 6 : m_bManualMapping = true;
226 6 : }
227 :
228 21 : void SetDotAsNestedField(bool bFlag)
229 : {
230 21 : m_bDotAsNestedField = bFlag;
231 21 : }
232 :
233 21 : void SetFID(const CPLString &m_osFIDIn)
234 : {
235 21 : m_osFID = m_osFIDIn;
236 21 : }
237 :
238 21 : void SetNextFID(GIntBig nNextFID)
239 : {
240 21 : m_nNextFID = nNextFID;
241 21 : }
242 :
243 : OGRElasticLayer *Clone();
244 :
245 3 : void SetOrderBy(const std::vector<OGRESSortDesc> &v)
246 : {
247 3 : m_aoSortColumns = v;
248 3 : }
249 :
250 3 : void SetFeatureDefnFinalized()
251 : {
252 3 : m_bFeatureDefnFinalized = true;
253 3 : }
254 :
255 : void GetGeomFieldProperties(int iGeomField, std::vector<CPLString> &aosPath,
256 : bool &bIsGeoPoint);
257 :
258 : static void ClampEnvelope(OGREnvelope &sEnvelope);
259 : };
260 :
261 : /************************************************************************/
262 : /* OGRElasticAggregationLayer */
263 : /************************************************************************/
264 :
265 : class OGRElasticAggregationLayer final
266 : : public OGRLayer,
267 : public OGRGetNextFeatureThroughRaw<OGRElasticAggregationLayer>
268 : {
269 :
270 : OGRElasticDataSource *m_poDS = nullptr;
271 : std::string m_osIndexName{};
272 : std::string m_osGeometryField{};
273 : OGRFeatureDefn *m_poFeatureDefn = nullptr;
274 : bool m_bFeaturesRequested = false;
275 : int m_iCurFeature = 0;
276 : bool m_bRequestHasSpatialFilter = false;
277 : int m_nGeohashGridMaxSize = 10000;
278 : int m_nGeohashGridPrecision = -1;
279 : CPLJSONObject m_oFieldDef{};
280 : CPLJSONObject m_oAggregatedFieldsRequest{};
281 : std::vector<std::unique_ptr<OGRFeature>> m_apoCachedFeatures{};
282 :
283 : explicit OGRElasticAggregationLayer(OGRElasticDataSource *poDS);
284 : std::string BuildRequest();
285 : void IssueAggregationRequest();
286 : OGRFeature *GetNextRawFeature();
287 :
288 : public:
289 : ~OGRElasticAggregationLayer() override;
290 :
291 3 : OGRFeatureDefn *GetLayerDefn() override
292 : {
293 3 : return m_poFeatureDefn;
294 : }
295 :
296 : void ResetReading() override;
297 7 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(OGRElasticAggregationLayer)
298 : GIntBig GetFeatureCount(int bForce) override;
299 : int TestCapability(const char *) override;
300 :
301 : OGRErr ISetSpatialFilter(int iGeomField,
302 : const OGRGeometry *poGeom) override;
303 :
304 : GDALDataset *GetDataset() override;
305 :
306 : static std::unique_ptr<OGRElasticAggregationLayer>
307 : Build(OGRElasticDataSource *poDS, const char *pszAggregation);
308 : };
309 :
310 : /************************************************************************/
311 : /* OGRElasticDataSource */
312 : /************************************************************************/
313 :
314 : class OGRElasticDataSource final : public GDALDataset
315 : {
316 : char *m_pszName;
317 : CPLString m_osURL;
318 : CPLString m_osUserPwd;
319 : CPLString m_osFID;
320 :
321 : std::set<CPLString> m_oSetLayers;
322 : std::vector<std::unique_ptr<OGRElasticLayer>> m_apoLayers;
323 : std::unique_ptr<OGRElasticAggregationLayer> m_poAggregationLayer{};
324 : bool m_bAllLayersListed = false;
325 : std::map<OGRLayer *, OGRLayer *> m_oMapResultSet;
326 : std::map<std::string, std::string> m_oMapHeadersFromEnv{};
327 :
328 : bool CheckVersion();
329 : int GetLayerIndex(const char *pszName);
330 : void FetchMapping(const char *pszIndexName);
331 : bool OpenAggregation(const char *pszAggregation);
332 : std::vector<std::string> GetIndexList(const char *pszQueriedIndexName);
333 :
334 : public:
335 : OGRElasticDataSource();
336 : virtual ~OGRElasticDataSource();
337 :
338 : bool m_bOverwrite;
339 : int m_nBulkUpload;
340 : char *m_pszWriteMap;
341 : char *m_pszMapping;
342 : int m_nBatchSize;
343 : int m_nFeatureCountToEstablishFeatureDefn;
344 : bool m_bJSonField;
345 : bool m_bFlattenNestedAttributes;
346 : bool m_bAddSourceIndexName = false; // Only used for wildcard layers
347 : int m_nMajorVersion = 0;
348 : int m_nMinorVersion = 0;
349 :
350 : bool Open(GDALOpenInfo *poOpenInfo);
351 :
352 : int Create(const char *pszFilename, char **papszOptions);
353 :
354 : CPLHTTPResult *HTTPFetch(const char *pszURL, CSLConstList papszOptions);
355 :
356 237 : const char *GetURL()
357 : {
358 237 : return m_osURL.c_str();
359 : }
360 :
361 0 : virtual const char *GetName()
362 : {
363 0 : return m_pszName;
364 : }
365 :
366 : virtual int GetLayerCount() override;
367 : virtual OGRLayer *GetLayer(int) override;
368 : virtual OGRLayer *GetLayerByName(const char *pszName) override;
369 :
370 : OGRLayer *ICreateLayer(const char *pszName,
371 : const OGRGeomFieldDefn *poGeomFieldDefn,
372 : CSLConstList papszOptions) override;
373 : virtual OGRErr DeleteLayer(int iLayer) override;
374 :
375 : virtual OGRLayer *ExecuteSQL(const char *pszSQLCommand,
376 : OGRGeometry *poSpatialFilter,
377 : const char *pszDialect) override;
378 : virtual void ReleaseResultSet(OGRLayer *poLayer) override;
379 :
380 : virtual int TestCapability(const char *) override;
381 :
382 : bool UploadFile(const CPLString &url, const CPLString &data,
383 : const CPLString &osVerb = CPLString());
384 : void Delete(const CPLString &url);
385 :
386 : json_object *RunRequest(
387 : const char *pszURL, const char *pszPostContent = nullptr,
388 : const std::vector<int> &anSilentedHTTPErrors = std::vector<int>());
389 :
390 90 : const CPLString &GetFID() const
391 : {
392 90 : return m_osFID;
393 : }
394 :
395 : void FetchMapping(const char *pszIndexName, std::set<CPLString> &oSetLayers,
396 : std::vector<std::unique_ptr<OGRElasticLayer>> &apoLayers);
397 : };
398 :
399 : #endif /* ndef _OGR_Elastic_H_INCLUDED */
|