Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GDAL 4 : * Purpose: Arrow Database Connectivity driver 5 : * Author: Even Rouault, <even dot rouault at spatialys.com> 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #include "ogrsf_frmts.h" 14 : #include "ogradbcdrivercore.h" 15 : #include "gdal_adbc.h" 16 : 17 : /************************************************************************/ 18 : /* IsDuckDB() */ 19 : /************************************************************************/ 20 : 21 17639 : bool OGRADBCDriverIsDuckDB(const GDALOpenInfo *poOpenInfo) 22 : { 23 18129 : return poOpenInfo->nHeaderBytes >= 20 && 24 490 : memcmp(poOpenInfo->pabyHeader + 8, "DUCK\x40\0\0\0\0\0\0\0", 25 17639 : 4 + 8) == 0; 26 : } 27 : 28 : /************************************************************************/ 29 : /* IsSQLite3() */ 30 : /************************************************************************/ 31 : 32 17632 : bool OGRADBCDriverIsSQLite3(const GDALOpenInfo *poOpenInfo) 33 : { 34 17632 : constexpr const char *SQLITE3_SIGNATURE = "SQLite format 3"; 35 17986 : return poOpenInfo->nHeaderBytes >= 512 && 36 354 : memcmp(poOpenInfo->pabyHeader, SQLITE3_SIGNATURE, 37 17632 : strlen(SQLITE3_SIGNATURE)) == 0; 38 : } 39 : 40 : /************************************************************************/ 41 : /* IsParquet() */ 42 : /************************************************************************/ 43 : 44 17639 : bool OGRADBCDriverIsParquet(const GDALOpenInfo *poOpenInfo) 45 : { 46 17639 : constexpr const char *PARQUET_SIGNATURE = "PAR1"; 47 17639 : return poOpenInfo->nHeaderBytes >= 48 18154 : static_cast<int>(strlen(PARQUET_SIGNATURE)) && 49 515 : memcmp(poOpenInfo->pabyHeader, PARQUET_SIGNATURE, 50 17639 : strlen(PARQUET_SIGNATURE)) == 0; 51 : } 52 : 53 : /************************************************************************/ 54 : /* OGRADBCDriverIdentify() */ 55 : /************************************************************************/ 56 : 57 48923 : int OGRADBCDriverIdentify(GDALOpenInfo *poOpenInfo) 58 : { 59 48923 : if (STARTS_WITH(poOpenInfo->pszFilename, "ADBC:")) 60 2 : return true; 61 : 62 48921 : if (STARTS_WITH(poOpenInfo->pszFilename, "/vsi")) 63 31283 : return false; 64 : 65 17638 : if (OGRADBCDriverIsDuckDB(poOpenInfo) || OGRADBCDriverIsParquet(poOpenInfo)) 66 : { 67 : #ifdef OGR_ADBC_HAS_DRIVER_MANAGER 68 : return true; 69 : #else 70 0 : const char *pszADBCDriverName = 71 : #ifdef _WIN32 72 : "duckdb.dll" 73 : #elif defined(__MACH__) && defined(__APPLE__) 74 : "libduckdb.dylib" 75 : #else 76 : "libduckdb.so" 77 : #endif 78 : ; 79 0 : return (GDALGetAdbcLoadDriverOverride() != nullptr || 80 0 : CPLGetSymbol(pszADBCDriverName, "duckdb_adbc_init") != nullptr); 81 : #endif 82 : } 83 : else 84 : { 85 35269 : return !poOpenInfo->IsExtensionEqualToCI("mbtiles") && 86 17631 : (OGRADBCDriverIsSQLite3(poOpenInfo) && 87 1 : ((!poOpenInfo->IsExtensionEqualToCI("gpkg") && 88 0 : (GDALGetDriverByName("SQLite") == nullptr || 89 1 : poOpenInfo->IsSingleAllowedDriver("ADBC"))) || 90 1 : (poOpenInfo->IsExtensionEqualToCI("gpkg") && 91 1 : (GDALGetDriverByName("GPKG") == nullptr || 92 1 : poOpenInfo->IsSingleAllowedDriver("ADBC"))))) 93 : #ifndef OGR_ADBC_HAS_DRIVER_MANAGER 94 35269 : && GDALGetAdbcLoadDriverOverride() != nullptr 95 : #endif 96 : ; 97 : } 98 : } 99 : 100 : /************************************************************************/ 101 : /* OGRADBCDriverSetCommonMetadata() */ 102 : /************************************************************************/ 103 : 104 2031 : void OGRADBCDriverSetCommonMetadata(GDALDriver *poDriver) 105 : { 106 2031 : poDriver->SetDescription(DRIVER_NAME); 107 2031 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES"); 108 2031 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Arrow Database Connectivity"); 109 2031 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/adbc.html"); 110 : 111 2031 : poDriver->SetMetadataItem(GDAL_DMD_CONNECTION_PREFIX, "ADBC:"); 112 : 113 2031 : poDriver->SetMetadataItem( 114 : GDAL_DMD_OPENOPTIONLIST, 115 : "<OpenOptionList>" 116 : " <Option name='ADBC_DRIVER' type='string' description='ADBC driver " 117 : "name'/>" 118 : " <Option name='SQL' type='string' " 119 : "description='SQL statement from which to build layer'/>" 120 : " <Option name='ADBC_OPTION_*' type='string' " 121 : "description='Option to pass to AdbcDatabaseSetOption()'/>" 122 : " <Option name='PRELUDE_STATEMENTS' type='string' description='SQL " 123 : "statement(s) to send on the database connection before any other " 124 : "ones'/>" 125 2031 : "</OpenOptionList>"); 126 2031 : poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, 127 2031 : "NATIVE OGRSQL SQLITE"); 128 : #ifdef OGR_ADBC_HAS_DRIVER_MANAGER 129 : poDriver->SetMetadataItem("HAS_ADBC_DRIVER_MANAGER", "YES"); 130 : #endif 131 : 132 2031 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES"); 133 2031 : poDriver->pfnIdentify = OGRADBCDriverIdentify; 134 2031 : } 135 : 136 : /************************************************************************/ 137 : /* DeclareDeferredOGRADBCPlugin() */ 138 : /************************************************************************/ 139 : 140 : #ifdef PLUGIN_FILENAME 141 1964 : void DeclareDeferredOGRADBCPlugin() 142 : { 143 1964 : if (GDALGetDriverByName(DRIVER_NAME) != nullptr) 144 : { 145 283 : return; 146 : } 147 1681 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME); 148 : #ifdef PLUGIN_INSTALLATION_MESSAGE 149 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE, 150 : PLUGIN_INSTALLATION_MESSAGE); 151 : #endif 152 1681 : OGRADBCDriverSetCommonMetadata(poDriver); 153 1681 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver); 154 : } 155 : #endif