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