LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/parquet - ogrparquetdrivercore.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 64 64 100.0 %
Date: 2025-10-27 00:14:23 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Parquet Translator
       4             :  * Purpose:  Implements OGRParquetDriver.
       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             : #include "gdal_frmts.h"
      14             : 
      15             : #ifdef PLUGIN_FILENAME
      16             : #include "gdalplugindriverproxy.h"
      17             : #endif
      18             : 
      19             : #include "ogrsf_frmts.h"
      20             : #include "gdal_priv.h"
      21             : 
      22             : #include "ogrparquetdrivercore.h"
      23             : 
      24             : /************************************************************************/
      25             : /*                             Identify()                               */
      26             : /************************************************************************/
      27             : 
      28             : template <size_t N> constexpr int constexpr_length(const char (&)[N])
      29             : {
      30             :     return static_cast<int>(N - 1);
      31             : }
      32             : 
      33       54103 : int OGRParquetDriverIdentify(GDALOpenInfo *poOpenInfo)
      34             : {
      35             : #if defined(GDAL_USE_ARROWDATASET) || defined(PLUGIN_FILENAME)
      36       54103 :     if (poOpenInfo->bIsDirectory)
      37             :     {
      38             :         // Might be a ParquetDataset
      39        1238 :         return -1;
      40             :     }
      41             : #endif
      42       52865 :     if (STARTS_WITH(poOpenInfo->pszFilename, "PARQUET:"))
      43         262 :         return TRUE;
      44             : 
      45             :     // See https://github.com/apache/parquet-format#file-format
      46       52603 :     bool bRet = false;
      47       52603 :     constexpr const char SIGNATURE[] = "PAR1";
      48       52603 :     constexpr int SIGNATURE_SIZE = constexpr_length(SIGNATURE);
      49             :     static_assert(SIGNATURE_SIZE == 4, "SIGNATURE_SIZE == 4");
      50       52603 :     constexpr int METADATASIZE_SIZE = 4;
      51       52603 :     if (poOpenInfo->fpL != nullptr &&
      52        3766 :         poOpenInfo->nHeaderBytes >=
      53        3630 :             SIGNATURE_SIZE + METADATASIZE_SIZE + SIGNATURE_SIZE &&
      54        3630 :         memcmp(poOpenInfo->pabyHeader, SIGNATURE, SIGNATURE_SIZE) == 0)
      55             :     {
      56        1782 :         VSIFSeekL(poOpenInfo->fpL, 0, SEEK_END);
      57        1782 :         const auto nFileSize = VSIFTellL(poOpenInfo->fpL);
      58        1782 :         VSIFSeekL(poOpenInfo->fpL,
      59             :                   nFileSize - (METADATASIZE_SIZE + SIGNATURE_SIZE), SEEK_SET);
      60        1782 :         uint32_t nMetadataSize = 0;
      61             :         static_assert(sizeof(nMetadataSize) == METADATASIZE_SIZE,
      62             :                       "sizeof(nMetadataSize) == METADATASIZE_SIZE");
      63        1782 :         VSIFReadL(&nMetadataSize, 1, sizeof(nMetadataSize), poOpenInfo->fpL);
      64        1782 :         CPL_LSBPTR32(&nMetadataSize);
      65        1782 :         unsigned char abyTrailingBytes[SIGNATURE_SIZE] = {0};
      66        1782 :         VSIFReadL(&abyTrailingBytes[0], 1, SIGNATURE_SIZE, poOpenInfo->fpL);
      67        3564 :         bRet = memcmp(abyTrailingBytes, SIGNATURE, SIGNATURE_SIZE) == 0 &&
      68        1782 :                nMetadataSize < nFileSize;
      69        1782 :         VSIFSeekL(poOpenInfo->fpL, 0, SEEK_SET);
      70             :     }
      71       52603 :     return bRet;
      72             : }
      73             : 
      74             : /************************************************************************/
      75             : /*                OGRParquetDriverSetCommonMetadata()                   */
      76             : /************************************************************************/
      77             : 
      78        1792 : void OGRParquetDriverSetCommonMetadata(GDALDriver *poDriver)
      79             : {
      80        1792 :     poDriver->SetDescription(DRIVER_NAME);
      81        1792 :     poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
      82        1792 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
      83        1792 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "(Geo)Parquet");
      84        1792 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "parquet");
      85        1792 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
      86        1792 :                               "drivers/vector/parquet.html");
      87        1792 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
      88        1792 :     poDriver->SetMetadataItem(GDAL_DCAP_MEASURED_GEOMETRIES, "YES");
      89        1792 :     poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES");
      90        1792 :     poDriver->SetMetadataItem(GDAL_DCAP_REOPEN_AFTER_WRITE_REQUIRED, "YES");
      91        1792 :     poDriver->SetMetadataItem(GDAL_DCAP_CAN_READ_AFTER_DELETE, "YES");
      92             : 
      93        1792 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES");
      94        1792 :     poDriver->SetMetadataItem(
      95             :         GDAL_DMD_CREATIONFIELDDATATYPES,
      96             :         "Integer Integer64 Real String Date Time DateTime "
      97        1792 :         "Binary IntegerList Integer64List RealList StringList");
      98        1792 :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATASUBTYPES,
      99        1792 :                               "Boolean Int16 Float32 JSON UUID");
     100        1792 :     poDriver->SetMetadataItem(GDAL_DMD_CREATION_FIELD_DEFN_FLAGS,
     101             :                               "WidthPrecision Nullable Comment "
     102        1792 :                               "AlternativeName Domain");
     103        1792 :     poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
     104             : 
     105        1792 :     poDriver->SetMetadataItem(
     106             :         GDAL_DMD_OPENOPTIONLIST,
     107             :         "<OpenOptionList>"
     108             :         "  <Option name='GEOM_POSSIBLE_NAMES' type='string' description='Comma "
     109             :         "separated list of possible names for geometry column(s).' "
     110             :         "default='geometry,wkb_geometry,wkt_geometry'/>"
     111             :         "  <Option name='CRS' type='string' "
     112             :         "description='Set/override CRS, typically defined as AUTH:CODE "
     113             :         "(e.g EPSG:4326), of geometry column(s)'/>"
     114        1792 :         "</OpenOptionList>");
     115             : 
     116        1792 :     poDriver->pfnIdentify = OGRParquetDriverIdentify;
     117        1792 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     118        1792 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
     119             : 
     120        1792 :     poDriver->SetMetadataItem(GDAL_DCAP_UPDATE, "YES");
     121        1792 :     poDriver->SetMetadataItem(GDAL_DMD_UPDATE_ITEMS, "Features");
     122             : 
     123        1792 :     poDriver->SetMetadataItem(GDAL_DCAP_DELETE_FIELD, "YES");
     124        1792 :     poDriver->SetMetadataItem(GDAL_DCAP_REORDER_FIELDS, "YES");
     125        1792 :     poDriver->SetMetadataItem(GDAL_DMD_ALTER_FIELD_DEFN_FLAGS,
     126        1792 :                               "Name Type WidthPrecision");
     127        1792 : }
     128             : 
     129             : /************************************************************************/
     130             : /*                  DeclareDeferredOGRParquetPlugin()                   */
     131             : /************************************************************************/
     132             : 
     133             : #ifdef PLUGIN_FILENAME
     134        2038 : void DeclareDeferredOGRParquetPlugin()
     135             : {
     136        2038 :     if (GDALGetDriverByName(DRIVER_NAME) != nullptr)
     137             :     {
     138         283 :         return;
     139             :     }
     140        1755 :     auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     141             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     142             :     poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     143             :                               PLUGIN_INSTALLATION_MESSAGE);
     144             : #endif
     145        1755 :     OGRParquetDriverSetCommonMetadata(poDriver);
     146        1755 :     GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     147             : }
     148             : #endif

Generated by: LCOV version 1.14