Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: Arrow generic code
4 : * Purpose: Arrow generic code
5 : * Author: Even Rouault, <even.rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2022, Planet Labs
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef OGR_ARROW_H
14 : #define OGR_ARROW_H
15 :
16 : #include "gdal_pam.h"
17 : #include "ogrsf_frmts.h"
18 :
19 : #include <map>
20 : #include <set>
21 :
22 : #include "ogr_include_arrow.h"
23 :
24 : enum class OGRArrowGeomEncoding
25 : {
26 : WKB,
27 : WKT,
28 :
29 : // F(ixed) S(ize) L(ist) of (x,y[,z][,m]) values / Interleaved layout
30 : GEOARROW_FSL_GENERIC, // only used by OGRArrowWriterLayer::m_eGeomEncoding
31 : GEOARROW_FSL_POINT,
32 : GEOARROW_FSL_LINESTRING,
33 : GEOARROW_FSL_POLYGON,
34 : GEOARROW_FSL_MULTIPOINT,
35 : GEOARROW_FSL_MULTILINESTRING,
36 : GEOARROW_FSL_MULTIPOLYGON,
37 :
38 : // Struct of (x,y,[,z][,m])
39 : GEOARROW_STRUCT_GENERIC, // only used by OGRArrowWriterLayer::m_eGeomEncoding
40 : GEOARROW_STRUCT_POINT,
41 : GEOARROW_STRUCT_LINESTRING,
42 : GEOARROW_STRUCT_POLYGON,
43 : GEOARROW_STRUCT_MULTIPOINT,
44 : GEOARROW_STRUCT_MULTILINESTRING,
45 : GEOARROW_STRUCT_MULTIPOLYGON,
46 : };
47 :
48 : /************************************************************************/
49 : /* OGRArrowIsGeoArrowStruct() */
50 : /************************************************************************/
51 :
52 260 : inline bool OGRArrowIsGeoArrowStruct(OGRArrowGeomEncoding eEncoding)
53 : {
54 260 : switch (eEncoding)
55 : {
56 260 : case OGRArrowGeomEncoding::GEOARROW_STRUCT_GENERIC:
57 : case OGRArrowGeomEncoding::GEOARROW_STRUCT_POINT:
58 : case OGRArrowGeomEncoding::GEOARROW_STRUCT_LINESTRING:
59 : case OGRArrowGeomEncoding::GEOARROW_STRUCT_POLYGON:
60 : case OGRArrowGeomEncoding::GEOARROW_STRUCT_MULTIPOINT:
61 : case OGRArrowGeomEncoding::GEOARROW_STRUCT_MULTILINESTRING:
62 : case OGRArrowGeomEncoding::GEOARROW_STRUCT_MULTIPOLYGON:
63 260 : return true;
64 :
65 0 : default:
66 0 : return false;
67 : }
68 : }
69 :
70 : /************************************************************************/
71 : /* OGRArrowLayer */
72 : /************************************************************************/
73 :
74 : class OGRArrowDataset;
75 :
76 : class OGRArrowLayer CPL_NON_FINAL
77 : : public OGRLayer,
78 : public OGRGetNextFeatureThroughRaw<OGRArrowLayer>
79 : {
80 : public:
81 : struct Constraint
82 : {
83 : enum class Type
84 : {
85 : Integer,
86 : Integer64,
87 : Real,
88 : String,
89 : };
90 : int iField = -1; // index to a OGRFeatureDefn OGRField
91 : int iArrayIdx = -1; // index to m_poBatchColumns
92 : int nOperation = -1; // SWQ_xxxx
93 : Type eType{};
94 : OGRField sValue{};
95 : std::string osValue{};
96 : };
97 :
98 : private:
99 : OGRArrowLayer(const OGRArrowLayer &) = delete;
100 : OGRArrowLayer &operator=(const OGRArrowLayer &) = delete;
101 :
102 : int m_nUseOptimizedAttributeFilter = -1;
103 : bool m_bSpatialFilterIntersectsLayerExtent = true;
104 : bool m_bUseRecordBatchBaseImplementation = false;
105 :
106 : // Modified by UseRecordBatchBaseImplementation()
107 : mutable struct ArrowSchema m_sCachedSchema = {};
108 :
109 : bool SkipToNextFeatureDueToAttributeFilter() const;
110 : void ExploreExprNode(const swq_expr_node *poNode);
111 : bool UseRecordBatchBaseImplementation() const;
112 :
113 : template <typename SourceOffset>
114 : static struct ArrowArray *
115 : CreateWKBArrayFromWKTArray(const struct ArrowArray *sourceArray);
116 :
117 : int GetArrowSchemaInternal(struct ArrowSchema *out) const;
118 :
119 : protected:
120 : OGRArrowDataset *m_poArrowDS = nullptr;
121 : arrow::MemoryPool *m_poMemoryPool = nullptr;
122 : OGRFeatureDefn *m_poFeatureDefn = nullptr;
123 : std::shared_ptr<arrow::Schema> m_poSchema{};
124 : std::string m_osFIDColumn{};
125 : int m_iFIDArrowColumn = -1;
126 : std::vector<std::vector<int>> m_anMapFieldIndexToArrowColumn{};
127 : std::vector<int> m_anMapGeomFieldIndexToArrowColumn{};
128 : std::vector<OGRArrowGeomEncoding> m_aeGeomEncoding{};
129 :
130 : //! Whether bounding box based spatial filter should be skipped.
131 : // This is set to true by OGRParquetDatasetLayer when there is a bounding
132 : // box field, as an optimization.
133 : bool m_bBaseArrowIgnoreSpatialFilterRect = false;
134 :
135 : //! Whether spatial filter should be skipped (by GetNextArrowArray())
136 : // This is set to true by OGRParquetDatasetLayer when filtering points in
137 : // a rectangle.
138 : bool m_bBaseArrowIgnoreSpatialFilter = false;
139 :
140 : //! Describe the bbox column of a geometry column
141 : struct GeomColBBOX
142 : {
143 : bool bIsFloat = false;
144 : int iArrowCol = -1;
145 : int iArrayIdx = -1; // only valid when m_bIgnoredFields == true
146 : int iArrowSubfieldXMin = -1;
147 : int iArrowSubfieldYMin = -1;
148 : int iArrowSubfieldXMax = -1;
149 : int iArrowSubfieldYMax = -1;
150 : };
151 :
152 : //! Map from OGR geometry field index to GeomColBBOX
153 : std::map<int, GeomColBBOX> m_oMapGeomFieldIndexToGeomColBBOX{};
154 :
155 : const arrow::BinaryArray *m_poArrayWKB = nullptr;
156 : const arrow::LargeBinaryArray *m_poArrayWKBLarge = nullptr;
157 : const arrow::Array *m_poArrayBBOX = nullptr;
158 : const arrow::DoubleArray *m_poArrayXMinDouble = nullptr;
159 : const arrow::DoubleArray *m_poArrayYMinDouble = nullptr;
160 : const arrow::DoubleArray *m_poArrayXMaxDouble = nullptr;
161 : const arrow::DoubleArray *m_poArrayYMaxDouble = nullptr;
162 : const arrow::FloatArray *m_poArrayXMinFloat = nullptr;
163 : const arrow::FloatArray *m_poArrayYMinFloat = nullptr;
164 : const arrow::FloatArray *m_poArrayXMaxFloat = nullptr;
165 : const arrow::FloatArray *m_poArrayYMaxFloat = nullptr;
166 :
167 : //! References values in range [0, m_poSchema->field_count()-1]
168 : std::set<int> m_oSetBBoxArrowColumns{};
169 :
170 : bool m_bIgnoredFields = false;
171 : std::vector<int>
172 : m_anMapFieldIndexToArrayIndex{}; // only valid when m_bIgnoredFields is
173 : // set
174 : std::vector<int> m_anMapGeomFieldIndexToArrayIndex{}; // only valid when
175 : // m_bIgnoredFields is set
176 : int m_nRequestedFIDColumn = -1; // only valid when m_bIgnoredFields is set
177 :
178 : int m_nExpectedBatchColumns =
179 : -1; // Should be equal to m_poBatch->num_columns() (when
180 : // m_bIgnoredFields is set)
181 :
182 : bool m_bEOF = false;
183 : int64_t m_nFeatureIdx = 0;
184 : int64_t m_nIdxInBatch = 0;
185 : std::map<std::string, CPLJSONObject> m_oMapGeometryColumns{};
186 : mutable std::map<int, OGREnvelope> m_oMapExtents{};
187 : int m_iRecordBatch = -1;
188 : std::shared_ptr<arrow::RecordBatch> m_poBatch{};
189 : // m_poBatch->columns() is a relatively costly operation, so cache its
190 : // result
191 : std::vector<std::shared_ptr<arrow::Array>>
192 : m_poBatchColumns{}; // must always be == m_poBatch->columns()
193 : mutable std::shared_ptr<arrow::Array> m_poReadFeatureTmpArray{};
194 :
195 : std::vector<Constraint> m_asAttributeFilterConstraints{};
196 :
197 : //! Whether attribute filter should be skipped.
198 : // This is set to true by OGRParquetDatasetLayer when it can fully translate
199 : // a filter, as an optimization.
200 : bool m_bBaseArrowIgnoreAttributeFilter = false;
201 :
202 : std::map<std::string, std::unique_ptr<OGRFieldDefn>>
203 : LoadGDALSchema(const arrow::KeyValueMetadata *kv_metadata);
204 :
205 : void LoadGDALMetadata(const arrow::KeyValueMetadata *kv_metadata);
206 :
207 : OGRArrowLayer(OGRArrowDataset *poDS, const char *pszLayerName);
208 :
209 : virtual std::string GetDriverUCName() const = 0;
210 : static bool IsIntegerArrowType(arrow::Type::type typeId);
211 : static bool
212 : IsHandledListOrMapType(const std::shared_ptr<arrow::DataType> &valueType);
213 : static bool
214 : IsHandledListType(const std::shared_ptr<arrow::BaseListType> &listType);
215 : static bool
216 : IsHandledMapType(const std::shared_ptr<arrow::MapType> &mapType);
217 : static bool
218 : IsValidGeometryEncoding(const std::shared_ptr<arrow::Field> &field,
219 : const std::string &osEncoding,
220 : bool bWarnIfUnknownEncoding,
221 : OGRwkbGeometryType &eGeomTypeOut,
222 : OGRArrowGeomEncoding &eGeomEncodingOut);
223 : static OGRwkbGeometryType
224 : GetGeometryTypeFromString(const std::string &osType);
225 : bool
226 : MapArrowTypeToOGR(const std::shared_ptr<arrow::DataType> &type,
227 : const std::shared_ptr<arrow::Field> &field,
228 : OGRFieldDefn &oField, OGRFieldType &eType,
229 : OGRFieldSubType &eSubType, const std::vector<int> &path,
230 : const std::map<std::string, std::unique_ptr<OGRFieldDefn>>
231 : &oMapFieldNameToGDALSchemaFieldDefn);
232 : void CreateFieldFromSchema(
233 : const std::shared_ptr<arrow::Field> &field,
234 : const std::vector<int> &path,
235 : const std::map<std::string, std::unique_ptr<OGRFieldDefn>>
236 : &oMapFieldNameToGDALSchemaFieldDefn);
237 : std::unique_ptr<OGRFieldDomain>
238 : BuildDomainFromBatch(const std::string &osDomainName,
239 : const std::shared_ptr<arrow::RecordBatch> &poBatch,
240 : int iCol) const;
241 : OGRwkbGeometryType ComputeGeometryColumnTypeProcessBatch(
242 : const std::shared_ptr<arrow::RecordBatch> &poBatch, int iGeomCol,
243 : int iBatchCol, OGRwkbGeometryType eGeomType) const;
244 : static bool ReadWKBBoundingBox(const uint8_t *data, size_t size,
245 : OGREnvelope &sEnvelope);
246 : OGRFeature *ReadFeature(
247 : int64_t nIdxInBatch,
248 : const std::vector<std::shared_ptr<arrow::Array>> &poColumnArrays) const;
249 : OGRGeometry *ReadGeometry(int iGeomField, const arrow::Array *array,
250 : int64_t nIdxInBatch) const;
251 : virtual bool ReadNextBatch() = 0;
252 : virtual void InvalidateCachedBatches() = 0;
253 : OGRFeature *GetNextRawFeature();
254 :
255 0 : virtual bool CanRunNonForcedGetExtent()
256 : {
257 0 : return true;
258 : }
259 :
260 : void SetBatch(const std::shared_ptr<arrow::RecordBatch> &poBatch);
261 :
262 : // Refreshes Constraint.iArrayIdx from iField. To be called by SetIgnoredFields()
263 : void ComputeConstraintsArrayIdx();
264 :
265 : static const swq_expr_node *GetColumnSubNode(const swq_expr_node *poNode);
266 : static const swq_expr_node *GetConstantSubNode(const swq_expr_node *poNode);
267 : static bool IsComparisonOp(int op);
268 :
269 : virtual bool FastGetExtent(int iGeomField, OGREnvelope *psExtent) const;
270 : bool FastGetExtent3D(int iGeomField, OGREnvelope3D *psExtent) const;
271 : static OGRErr GetExtentFromMetadata(const CPLJSONObject &oJSONDef,
272 : OGREnvelope3D *psExtent);
273 :
274 : int GetArrowSchema(struct ArrowArrayStream *,
275 : struct ArrowSchema *out) override;
276 : int GetNextArrowArray(struct ArrowArrayStream *,
277 : struct ArrowArray *out) override;
278 :
279 4695 : virtual void IncrFeatureIdx()
280 : {
281 4695 : ++m_nFeatureIdx;
282 4695 : }
283 :
284 : void SanityCheckOfSetBatch() const;
285 :
286 : public:
287 : virtual ~OGRArrowLayer() override;
288 :
289 13925 : OGRFeatureDefn *GetLayerDefn() override
290 : {
291 13925 : return m_poFeatureDefn;
292 : }
293 :
294 : void ResetReading() override;
295 :
296 1874 : const char *GetFIDColumn() override
297 : {
298 1874 : return m_osFIDColumn.c_str();
299 : }
300 9047 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(OGRArrowLayer)
301 : OGRErr GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
302 : OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent,
303 : int bForce = TRUE) override;
304 : OGRErr GetExtent3D(int iGeomField, OGREnvelope3D *psExtent,
305 : int bForce = TRUE) override;
306 : OGRErr SetAttributeFilter(const char *pszFilter) override;
307 :
308 713 : void SetSpatialFilter(OGRGeometry *poGeom) override
309 : {
310 713 : SetSpatialFilter(0, poGeom);
311 713 : }
312 :
313 : void SetSpatialFilter(int iGeomField, OGRGeometry *poGeom) override;
314 :
315 : int TestCapability(const char *pszCap) override;
316 :
317 : bool GetArrowStream(struct ArrowArrayStream *out_stream,
318 : CSLConstList papszOptions = nullptr) override;
319 :
320 : virtual std::unique_ptr<OGRFieldDomain>
321 : BuildDomain(const std::string &osDomainName, int iFieldIndex) const = 0;
322 :
323 : static void TimestampToOGR(int64_t timestamp,
324 : const arrow::TimestampType *timestampType,
325 : int nTZFlag, OGRField *psField);
326 : };
327 :
328 : /************************************************************************/
329 : /* OGRArrowDataset */
330 : /************************************************************************/
331 :
332 : class OGRArrowDataset CPL_NON_FINAL : public GDALPamDataset
333 : {
334 : std::shared_ptr<arrow::MemoryPool> m_poMemoryPool{};
335 : std::unique_ptr<OGRArrowLayer> m_poLayer{};
336 : std::vector<std::string> m_aosDomainNames{};
337 : std::map<std::string, int> m_oMapDomainNameToCol{};
338 :
339 : protected:
340 1118 : void close()
341 : {
342 1118 : m_poLayer.reset();
343 1118 : m_poMemoryPool.reset();
344 1118 : }
345 :
346 : public:
347 : explicit OGRArrowDataset(
348 : const std::shared_ptr<arrow::MemoryPool> &poMemoryPool);
349 :
350 1663 : inline arrow::MemoryPool *GetMemoryPool() const
351 : {
352 1663 : return m_poMemoryPool.get();
353 : }
354 :
355 609 : inline const std::shared_ptr<arrow::MemoryPool> &GetSharedMemoryPool() const
356 : {
357 609 : return m_poMemoryPool;
358 : }
359 :
360 : void SetLayer(std::unique_ptr<OGRArrowLayer> &&poLayer);
361 :
362 : void RegisterDomainName(const std::string &osDomainName, int iFieldIndex);
363 :
364 : std::vector<std::string> GetFieldDomainNames(
365 : CSLConstList /*papszOptions*/ = nullptr) const override;
366 : const OGRFieldDomain *
367 : GetFieldDomain(const std::string &name) const override;
368 :
369 : int GetLayerCount() override;
370 : OGRLayer *GetLayer(int idx) override;
371 : };
372 :
373 : /************************************************************************/
374 : /* OGRArrowWriterLayer */
375 : /************************************************************************/
376 :
377 : class OGRArrowWriterLayer CPL_NON_FINAL : public OGRLayer
378 :
379 : {
380 : protected:
381 : OGRArrowWriterLayer(const OGRArrowWriterLayer &) = delete;
382 : OGRArrowWriterLayer &operator=(const OGRArrowWriterLayer &) = delete;
383 :
384 : arrow::MemoryPool *m_poMemoryPool = nullptr;
385 : bool m_bInitializationOK = false;
386 : std::shared_ptr<arrow::io::OutputStream> m_poOutputStream{};
387 : std::shared_ptr<arrow::Schema> m_poSchema{};
388 : OGRFeatureDefn *m_poFeatureDefn = nullptr;
389 : std::map<std::string, std::unique_ptr<OGRFieldDomain>> m_oMapFieldDomains{};
390 : std::map<std::string, std::shared_ptr<arrow::Array>>
391 : m_oMapFieldDomainToStringArray{};
392 :
393 : bool m_bWriteFieldArrowExtensionName = false;
394 : OGRArrowGeomEncoding m_eGeomEncoding = OGRArrowGeomEncoding::WKB;
395 : std::vector<OGRArrowGeomEncoding> m_aeGeomEncoding{};
396 : int m_nWKTCoordinatePrecision = -1;
397 :
398 : //! Base struct data type for GeoArrow struct geometry columns.
399 : // Constraint: if not empty, m_apoBaseStructGeomType.size() == m_poFeatureDefn->GetGeomFieldCount()
400 : std::vector<std::shared_ptr<arrow::DataType>> m_apoBaseStructGeomType{};
401 :
402 : //! Whether to use a struct field with the values of the bounding box
403 : // of the geometries. Used by Parquet.
404 : bool m_bWriteBBoxStruct = false;
405 :
406 : //! Schema fields for bounding box of geometry columns.
407 : // Constraint: if not empty, m_apoFieldsBBOX.size() == m_poFeatureDefn->GetGeomFieldCount()
408 : std::vector<std::shared_ptr<arrow::Field>> m_apoFieldsBBOX{};
409 :
410 : //! Array builers for bounding box of geometry columns.
411 : // m_apoBuildersBBOXStruct is for the top-level field of type struct.
412 : // m_apoBuildersBBOX{XMin|YMin|XMax|YMax} are for the floating-point values
413 : // Constraint: if not empty, m_apoBuildersBBOX{Struct|XMin|YMin|XMax|YMax}.size() == m_poFeatureDefn->GetGeomFieldCount()
414 : std::vector<std::shared_ptr<arrow::StructBuilder>>
415 : m_apoBuildersBBOXStruct{};
416 : std::vector<std::shared_ptr<arrow::FloatBuilder>> m_apoBuildersBBOXXMin{};
417 : std::vector<std::shared_ptr<arrow::FloatBuilder>> m_apoBuildersBBOXYMin{};
418 : std::vector<std::shared_ptr<arrow::FloatBuilder>> m_apoBuildersBBOXXMax{};
419 : std::vector<std::shared_ptr<arrow::FloatBuilder>> m_apoBuildersBBOXYMax{};
420 :
421 : std::string m_osFIDColumn{};
422 : int64_t m_nFeatureCount = 0;
423 :
424 : int64_t m_nRowGroupSize = 64 * 1024;
425 : arrow::Compression::type m_eCompression = arrow::Compression::UNCOMPRESSED;
426 :
427 : std::vector<std::shared_ptr<arrow::Field>> m_apoFieldsFromArrowSchema{};
428 : std::vector<std::shared_ptr<arrow::ArrayBuilder>> m_apoBuilders{};
429 :
430 : std::vector<uint8_t> m_abyBuffer{};
431 :
432 : std::vector<int> m_anTZFlag{}; // size: GetFieldCount()
433 : std::vector<OGREnvelope3D> m_aoEnvelopes{}; // size: GetGeomFieldCount()
434 : std::vector<std::set<OGRwkbGeometryType>>
435 : m_oSetWrittenGeometryTypes{}; // size: GetGeomFieldCount()
436 :
437 : static OGRArrowGeomEncoding
438 : GetPreciseArrowGeomEncoding(OGRArrowGeomEncoding eEncodingType,
439 : OGRwkbGeometryType eGType);
440 : static const char *
441 : GetGeomEncodingAsString(OGRArrowGeomEncoding eGeomEncoding,
442 : bool bForParquetGeo);
443 :
444 : virtual bool IsSupportedGeometryType(OGRwkbGeometryType eGType) const = 0;
445 :
446 : virtual std::string GetDriverUCName() const = 0;
447 :
448 : virtual bool IsFileWriterCreated() const = 0;
449 : virtual void CreateWriter() = 0;
450 : virtual bool CloseFileWriter() = 0;
451 :
452 : void CreateSchemaCommon();
453 : void FinalizeSchema();
454 : virtual void CreateSchema() = 0;
455 :
456 0 : virtual void PerformStepsBeforeFinalFlushGroup()
457 : {
458 0 : }
459 :
460 : void CreateArrayBuilders();
461 :
462 : //! Clear array builders
463 : void ClearArrayBuilers();
464 :
465 : virtual bool FlushGroup() = 0;
466 : bool FinalizeWriting();
467 : bool WriteArrays(std::function<bool(const std::shared_ptr<arrow::Field> &,
468 : const std::shared_ptr<arrow::Array> &)>
469 : postProcessArray);
470 :
471 128 : virtual void FixupWKBGeometryBeforeWriting(GByte * /*pabyWKB*/,
472 : size_t /*nLen*/)
473 : {
474 128 : }
475 :
476 0 : virtual void FixupGeometryBeforeWriting(OGRGeometry * /* poGeom */)
477 : {
478 0 : }
479 :
480 : virtual bool IsSRSRequired() const = 0;
481 : bool WriteArrowBatchInternal(
482 : const struct ArrowSchema *schema, struct ArrowArray *array,
483 : CSLConstList papszOptions,
484 : std::function<bool(const std::shared_ptr<arrow::RecordBatch> &)>
485 : writeBatch);
486 :
487 : OGRErr BuildGeometry(OGRGeometry *poGeom, int iGeomField,
488 : arrow::ArrayBuilder *poBuilder);
489 :
490 : public:
491 : OGRArrowWriterLayer(
492 : arrow::MemoryPool *poMemoryPool,
493 : const std::shared_ptr<arrow::io::OutputStream> &poOutputStream,
494 : const char *pszLayerName);
495 :
496 : ~OGRArrowWriterLayer() override;
497 :
498 : bool AddFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
499 : std::string &failureReason);
500 : std::vector<std::string> GetFieldDomainNames() const;
501 : const OGRFieldDomain *GetFieldDomain(const std::string &name) const;
502 :
503 7 : const char *GetFIDColumn() override
504 : {
505 7 : return m_osFIDColumn.c_str();
506 : }
507 :
508 6056 : OGRFeatureDefn *GetLayerDefn() override
509 : {
510 6056 : return m_poFeatureDefn;
511 : }
512 :
513 23 : void ResetReading() override
514 : {
515 23 : }
516 :
517 23 : OGRFeature *GetNextFeature() override
518 : {
519 23 : return nullptr;
520 : }
521 :
522 : int TestCapability(const char *pszCap) override;
523 : OGRErr CreateField(const OGRFieldDefn *poField,
524 : int bApproxOK = TRUE) override;
525 : OGRErr CreateGeomField(const OGRGeomFieldDefn *poField,
526 : int bApproxOK = TRUE) override;
527 : GIntBig GetFeatureCount(int bForce) override;
528 :
529 112 : bool IsArrowSchemaSupported(const struct ArrowSchema * /*schema*/,
530 : CSLConstList /* papszOptions */,
531 : std::string & /*osErrorMsg */) const override
532 : {
533 112 : return true;
534 : }
535 :
536 : bool
537 : CreateFieldFromArrowSchema(const struct ArrowSchema *schema,
538 : CSLConstList papszOptions = nullptr) override;
539 : bool WriteArrowBatch(const struct ArrowSchema *schema,
540 : struct ArrowArray *array,
541 : CSLConstList papszOptions = nullptr) override = 0;
542 :
543 : protected:
544 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
545 :
546 : bool FlushFeatures();
547 : };
548 :
549 : #endif // OGR_ARROW_H
|