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 17571 : bool OGRADBCDriverIsDuckDB(const GDALOpenInfo *poOpenInfo) 22 : { 23 18051 : return poOpenInfo->nHeaderBytes >= 20 && 24 480 : memcmp(poOpenInfo->pabyHeader + 8, "DUCK\x40\0\0\0\0\0\0\0", 25 17571 : 4 + 8) == 0; 26 : } 27 : 28 : /************************************************************************/ 29 : /* IsSQLite3() */ 30 : /************************************************************************/ 31 : 32 17564 : bool OGRADBCDriverIsSQLite3(const GDALOpenInfo *poOpenInfo) 33 : { 34 17564 : constexpr const char *SQLITE3_SIGNATURE = "SQLite format 3"; 35 17908 : return poOpenInfo->nHeaderBytes >= 512 && 36 344 : memcmp(poOpenInfo->pabyHeader, SQLITE3_SIGNATURE, 37 17564 : strlen(SQLITE3_SIGNATURE)) == 0; 38 : } 39 : 40 : /************************************************************************/ 41 : /* IsParquet() */ 42 : /************************************************************************/ 43 : 44 17571 : bool OGRADBCDriverIsParquet(const GDALOpenInfo *poOpenInfo) 45 : { 46 17571 : constexpr const char *PARQUET_SIGNATURE = "PAR1"; 47 17571 : return poOpenInfo->nHeaderBytes >= 48 18076 : static_cast<int>(strlen(PARQUET_SIGNATURE)) && 49 505 : memcmp(poOpenInfo->pabyHeader, PARQUET_SIGNATURE, 50 17571 : strlen(PARQUET_SIGNATURE)) == 0; 51 : } 52 : 53 : /************************************************************************/ 54 : /* OGRADBCDriverIdentify() */ 55 : /************************************************************************/ 56 : 57 49334 : int OGRADBCDriverIdentify(GDALOpenInfo *poOpenInfo) 58 : { 59 49334 : if (STARTS_WITH(poOpenInfo->pszFilename, "ADBC:")) 60 2 : return true; 61 : 62 49332 : if (STARTS_WITH(poOpenInfo->pszFilename, "/vsi")) 63 31762 : return false; 64 : 65 17570 : 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 35133 : return !poOpenInfo->IsExtensionEqualToCI("mbtiles") && 86 17563 : (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 35133 : && GDALGetAdbcLoadDriverOverride() != nullptr 95 : #endif 96 : ; 97 : } 98 : } 99 : 100 : /************************************************************************/ 101 : /* OGRADBCDriverSetCommonMetadata() */ 102 : /************************************************************************/ 103 : 104 1663 : void OGRADBCDriverSetCommonMetadata(GDALDriver *poDriver) 105 : { 106 1663 : poDriver->SetDescription(DRIVER_NAME); 107 1663 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES"); 108 1663 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Arrow Database Connectivity"); 109 1663 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/adbc.html"); 110 : 111 1663 : poDriver->SetMetadataItem(GDAL_DMD_CONNECTION_PREFIX, "ADBC:"); 112 : 113 1663 : 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 1663 : "</OpenOptionList>"); 126 1663 : poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, 127 1663 : "NATIVE OGRSQL SQLITE"); 128 : #ifdef OGR_ADBC_HAS_DRIVER_MANAGER 129 : poDriver->SetMetadataItem("HAS_ADBC_DRIVER_MANAGER", "YES"); 130 : #endif 131 : 132 1663 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES"); 133 1663 : poDriver->pfnIdentify = OGRADBCDriverIdentify; 134 1663 : } 135 : 136 : /************************************************************************/ 137 : /* DeclareDeferredOGRADBCPlugin() */ 138 : /************************************************************************/ 139 : 140 : #ifdef PLUGIN_FILENAME 141 1935 : void DeclareDeferredOGRADBCPlugin() 142 : { 143 1935 : if (GDALGetDriverByName(DRIVER_NAME) != nullptr) 144 : { 145 282 : return; 146 : } 147 1653 : 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 1653 : OGRADBCDriverSetCommonMetadata(poDriver); 153 1653 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver); 154 : } 155 : #endif