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

Generated by: LCOV version 1.14