182 OGRwkbGeometryType ogr_geometry_type = wkbUnknown;
183 int num_geo_columns = 0;
184 int geo_column_srid = 0;
185 uint32_t num_columns = 0;
186 std::string geo_column_name;
187 for (
auto const& column_info : column_infos) {
188 auto const& type_info = column_info.get_type_info();
189 if (type_info.is_geometry()) {
190 switch (type_info.get_type()) {
192 ogr_geometry_type = wkbPoint;
195 ogr_geometry_type = wkbLineString;
198 ogr_geometry_type = wkbPolygon;
201 ogr_geometry_type = wkbMultiPolygon;
206 geo_column_srid = type_info.get_output_srid();
207 geo_column_name =
safeColumnName(column_info.get_resname(), num_columns + 1);
210 auto column_name =
safeColumnName(column_info.get_resname(), num_columns + 1);
216 if (num_geo_columns != 1) {
217 throw std::runtime_error(
"File type '" +
219 "' requires exactly one geo column in query results");
223 if (geo_column_srid <= 0) {
224 throw std::runtime_error(
"Geo column '" + geo_column_name +
"' has invalid SRID (" +
226 "). Use ST_SetSRID() in query to override.");
231 auto gdal_driver = GetGDALDriverManager()->GetDriverByName(driver_name);
232 if (gdal_driver ==
nullptr) {
233 throw std::runtime_error(
"Failed to find Driver '" + std::string(driver_name) +
238 auto gdal_file_path{file_path};
239 auto user_file_path{file_path};
244 throw std::runtime_error(
245 "Selected file compression option not yet supported for file type '" +
255 auto remove_file = [](
const std::string&
filename) {
256 if (boost::filesystem::exists(
filename)) {
258 boost::filesystem::remove(
filename);
261 remove_file(file_path);
262 remove_file(user_file_path);
264 LOG(
INFO) <<
"Exporting to file '" << user_file_path <<
"'";
268 gdal_driver->Create(gdal_file_path.c_str(), 0, 0, 0, GDT_Unknown, NULL);
270 throw std::runtime_error(
"Failed to create File '" + file_path +
"'");
274 OGRSpatialReference ogr_spatial_reference;
275 if (ogr_spatial_reference.importFromEPSG(geo_column_srid)) {
276 throw std::runtime_error(
"Failed to create Spatial Reference for SRID " +
279 #if GDAL_VERSION_MAJOR >= 3
280 ogr_spatial_reference.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
285 layer_name.c_str(), &ogr_spatial_reference, ogr_geometry_type, NULL);
287 throw std::runtime_error(
"Failed to create Layer '" + layer_name +
"'");
291 int column_index = 0;
294 for (
auto const& column_info : column_infos) {
295 auto column_name =
safeColumnName(column_info.get_resname(), column_index + 1);
297 auto const& type_info = column_info.get_type_info();
298 if (!type_info.is_geometry()) {
299 OGRFieldDefn field_defn(
302 if (
ogr_layer_->CreateField(&field_defn) != OGRERR_NONE) {
303 throw std::runtime_error(
"Failed to create Field '" + column_name +
"'");
312 }
catch (std::exception& e) {
313 LOG(
INFO) <<
"GDAL Query Export failed to start: " << e.what();
static constexpr std::array< const char *, 5 > file_type_names
const FileType file_type_
static constexpr std::array< std::array< bool, 3 >, 5 > compression_implemented
std::string safeColumnName(const std::string &resname, const int column_index)
static std::array< std::unordered_set< std::string >, 5 > file_type_valid_extensions
ArrayNullHandling array_null_handling_
static constexpr std::array< const char *, 3 > compression_prefix
OGRFieldType sql_type_info_to_ogr_field_type(const std::string &name, const SQLTypeInfo &type_info, const QueryExporter::FileType file_type)
static constexpr std::array< const char *, 3 > compression_suffix
std::vector< int > field_indices_
std::string filename(char const *path)
void validateFileExtensions(const std::string &file_path, const std::string &file_type, const std::unordered_set< std::string > &valid_extensions) const
static constexpr std::array< const char *, 5 > driver_names
GDALDataset * gdal_dataset_