2929#include " cpl_vsi_virtual.h"
3030#include " duckdb/common/types/geometry_crs.hpp"
3131#include " duckdb/main/settings.hpp"
32+ #include " spatial/spatial_settings.hpp"
33+ #include " spatial/modules/proj/proj_module.hpp"
3234
3335namespace duckdb {
3436namespace {
@@ -393,6 +395,8 @@ class DuckDBFileSystemHandler final : public VSIFilesystemHandler {
393395
394396class DuckDBFileSystemPrefix final : public ClientContextState {
395397public:
398+ static mutex vsi_mutex;
399+
396400 explicit DuckDBFileSystemPrefix (ClientContext &context) : context(context) {
397401 // Create a new random prefix for this client
398402 client_prefix = StringUtil::Format (" /vsiduckdb-%s/" , UUID::ToString (UUID::GenerateRandomUUID ()));
@@ -401,11 +405,13 @@ class DuckDBFileSystemPrefix final : public ClientContextState {
401405 fs_handler = make_uniq<DuckDBFileSystemHandler>(client_prefix, context);
402406
403407 // Register the file handler
408+ lock_guard<mutex> lock (vsi_mutex);
404409 VSIFileManager::InstallHandler (client_prefix, fs_handler.get ());
405410 }
406411
407412 ~DuckDBFileSystemPrefix () override {
408413 // Uninstall the file handler for this prefix
414+ lock_guard<mutex> lock (vsi_mutex);
409415 VSIFileManager::RemoveHandler (client_prefix);
410416 }
411417
@@ -430,6 +436,8 @@ class DuckDBFileSystemPrefix final : public ClientContextState {
430436 unique_ptr<DuckDBFileSystemHandler> fs_handler;
431437};
432438
439+ mutex DuckDBFileSystemPrefix::vsi_mutex;
440+
433441// ======================================================================================================================
434442// GDAL READ
435443// ======================================================================================================================
@@ -628,6 +636,35 @@ auto Bind(ClientContext &ctx, TableFunctionBindInput &input, vector<LogicalType>
628636 col_names.push_back (child_schema.name );
629637 }
630638
639+ if (duck_type.id () != LogicalTypeId::GEOMETRY) {
640+ col_types.push_back (std::move (duck_type));
641+ continue ;
642+ }
643+
644+ if (!GeoType::HasCRS (duck_type)) {
645+ col_types.push_back (std::move (duck_type));
646+ continue ;
647+ }
648+
649+ // Try to identify the CRS
650+ const auto &gdal_crs = GeoType::GetCRS (duck_type);
651+
652+ // FIXME: GDAL should be able to do this on its own, but somehow
653+ // OGRSpatialReference::FindBestMatch() dont work
654+
655+ string auth_name;
656+ string auth_code;
657+ if (IdentifyProjCRS (gdal_crs.GetDefinition ().c_str (), auth_name, auth_code)) {
658+ // If we can identify the CRS using PROJ, we can be pretty sure that DuckDB will recognize it.
659+ auto authcode = auth_name + " :" + auth_code;
660+ auto duck_crs = CoordinateReferenceSystem::TryIdentify (ctx, authcode);
661+ if (duck_crs) {
662+ col_types.push_back (LogicalType::GEOMETRY (*duck_crs));
663+ continue ;
664+ }
665+ }
666+
667+ // Otherwise just pass on what we got
631668 col_types.push_back (std::move (duck_type));
632669 }
633670
@@ -1295,7 +1332,25 @@ auto InitGlobal(ClientContext &context, FunctionData &bdata_p, const string &rea
12951332 if (!bdata.target_srs .empty ()) {
12961333 // Make a new spatial reference object, and set it from the user input
12971334 result->srs = OSRNewSpatialReference (nullptr );
1298- OSRSetFromUserInput (result->srs , bdata.target_srs .c_str ());
1335+
1336+ // Try get the complete SRS from duckdb
1337+ auto converted =
1338+ CoordinateReferenceSystem::TryConvert (context, bdata.target_srs , CoordinateReferenceSystemType::PROJJSON);
1339+ if (!converted) {
1340+ converted = CoordinateReferenceSystem::TryConvert (context, bdata.target_srs ,
1341+ CoordinateReferenceSystemType::WKT2_2019);
1342+ if (!converted) {
1343+ converted = CoordinateReferenceSystem::TryConvert (context, bdata.target_srs ,
1344+ CoordinateReferenceSystemType::AUTH_CODE);
1345+ }
1346+ }
1347+
1348+ if (converted) {
1349+ OSRSetFromUserInput (result->srs , converted->GetDefinition ().c_str ());
1350+ } else {
1351+ // Try to set it directly from the user input, in case it's in a format that duckdb doesn't recognize but GDAL does
1352+ OSRSetFromUserInput (result->srs , bdata.target_srs .c_str ());
1353+ }
12991354 }
13001355
13011356 // Create Layer
0 commit comments