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

Generated by: LCOV version 1.14