Skip to content

Commit 173b746

Browse files
authored
Merge pull request #536 from Maxxen/v1.2.1-dev
Update function reference
2 parents fd5fd30 + db2f46f commit 173b746

10 files changed

+925
-461
lines changed

Makefile

-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ PROJ_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
44
EXT_NAME=excel
55
EXT_CONFIG=${PROJ_DIR}extension_config.cmake
66

7-
CORE_EXTENSIONS='httpfs'
8-
97
# Include the Makefile from extension-ci-tools
108
include extension-ci-tools/makefiles/duckdb_extension.Makefile
119

docs/functions.md

+836-431
Large diffs are not rendered by default.

src/spatial/modules/gdal/gdal_module.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -1105,7 +1105,7 @@ struct ST_Read : ArrowTableFunction {
11051105
func.named_parameters["keep_wkb"] = LogicalType::BOOLEAN;
11061106
ExtensionUtil::RegisterFunction(db, func);
11071107

1108-
FunctionBuilder::AddTableFunctionDocs(db, "ST_Read", DOCUMENTATION, EXAMPLE);
1108+
FunctionBuilder::AddTableFunctionDocs(db, "ST_Read", DOCUMENTATION, EXAMPLE, {{"ext", "spatial"}});
11091109

11101110
// Replacement scan
11111111
auto &config = DBConfig::GetConfig(db);
@@ -1326,7 +1326,7 @@ struct ST_Read_Meta {
13261326
const TableFunction func("ST_Read_Meta", {LogicalType::VARCHAR}, Execute, Bind, Init);
13271327
ExtensionUtil::RegisterFunction(db, MultiFileReader::CreateFunctionSet(func));
13281328

1329-
FunctionBuilder::AddTableFunctionDocs(db, "ST_Read_Meta", DESCRIPTION, EXAMPLE);
1329+
FunctionBuilder::AddTableFunctionDocs(db, "ST_Read_Meta", DESCRIPTION, EXAMPLE, {{"ext", "spatial"}});
13301330
}
13311331
};
13321332

@@ -1447,7 +1447,7 @@ struct ST_Drivers {
14471447
const TableFunction func("ST_Drivers", {}, Execute, Bind, Init);
14481448
ExtensionUtil::RegisterFunction(db, func);
14491449

1450-
FunctionBuilder::AddTableFunctionDocs(db, "ST_Drivers", DESCRIPTION, EXAMPLE);
1450+
FunctionBuilder::AddTableFunctionDocs(db, "ST_Drivers", DESCRIPTION, EXAMPLE, {{"ext", "spatial"}});
14511451
}
14521452
};
14531453

src/spatial/modules/geos/geos_module.cpp

+22-12
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ struct ST_Boundary {
219219
variant.SetFunction(Execute);
220220
});
221221

222-
func.SetDescription("Returns the boundary of a geometry");
222+
func.SetDescription("Returns the \"boundary\" of a geometry");
223223
func.SetTag("ext", "spatial");
224224
func.SetTag("category", "construction");
225225
});
@@ -431,7 +431,12 @@ struct ST_Contains : AsymmetricPreparedBinaryFunction<ST_Contains> {
431431
variant.SetFunction(Execute);
432432
});
433433

434-
func.SetDescription("Returns true if the first geometry contains the second geometry");
434+
func.SetDescription(R"(
435+
Returns true if the first geometry contains the second geometry
436+
437+
In contrast to `ST_ContainsProperly`, this function will also return true if `geom2` is contained strictly on the boundary of `geom1`.
438+
A geometry always `ST_Contains` itself, but does not `ST_ContainsProperly` itself.
439+
)");
435440
func.SetTag("ext", "spatial");
436441
func.SetTag("category", "relation");
437442
});
@@ -460,7 +465,12 @@ struct ST_ContainsProperly : AsymmetricPreparedBinaryFunction<ST_ContainsProperl
460465
variant.SetFunction(Execute);
461466
});
462467

463-
func.SetDescription("Returns true if the first geometry contains the second geometry properly");
468+
func.SetDescription(R"(
469+
Returns true if the first geometry \"properly\" contains the second geometry
470+
471+
In contrast to `ST_Contains`, this function does not return true if `geom2` is contained strictly on the boundary of `geom1`.
472+
A geometry always `ST_Contains` itself, but does not `ST_ContainsProperly` itself.
473+
)");
464474
func.SetTag("ext", "spatial");
465475
func.SetTag("category", "relation");
466476
});
@@ -791,7 +801,7 @@ struct ST_CoveredBy : AsymmetricPreparedBinaryFunction<ST_CoveredBy> {
791801
variant.SetFunction(Execute);
792802
});
793803

794-
func.SetDescription("Returns true if the first geometry is covered by the second geometry");
804+
func.SetDescription("Returns true if geom1 is \"covered by\" geom2");
795805
func.SetTag("ext", "spatial");
796806
func.SetTag("category", "relation");
797807
});
@@ -816,7 +826,7 @@ struct ST_Covers : AsymmetricPreparedBinaryFunction<ST_Covers> {
816826
variant.SetFunction(Execute);
817827
});
818828

819-
func.SetDescription("Returns true if the first geometry covers the second geometry");
829+
func.SetDescription("Returns true if the geom1 \"covers\" geom2");
820830
func.SetTag("ext", "spatial");
821831
func.SetTag("category", "relation");
822832
});
@@ -841,7 +851,7 @@ struct ST_Crosses : SymmetricPreparedBinaryFunction<ST_Crosses> {
841851
variant.SetFunction(Execute);
842852
});
843853

844-
func.SetDescription("Returns true if the geometries cross each other");
854+
func.SetDescription("Returns true if geom1 \"crosses\" geom2");
845855
func.SetTag("ext", "spatial");
846856
func.SetTag("category", "relation");
847857
});
@@ -872,7 +882,7 @@ struct ST_Difference {
872882
variant.SetFunction(Execute);
873883
});
874884

875-
func.SetDescription("Returns the difference between two geometries");
885+
func.SetDescription("Returns the \"difference\" between two geometries");
876886
func.SetTag("ext", "spatial");
877887
func.SetTag("category", "construction");
878888
});
@@ -1045,7 +1055,7 @@ struct ST_Equals {
10451055
variant.SetFunction(Execute);
10461056
});
10471057

1048-
func.SetDescription("Returns true if the geometries are equal");
1058+
func.SetDescription("Returns true if the geometries are \"equal\"");
10491059
func.SetTag("ext", "spatial");
10501060
func.SetTag("category", "relation");
10511061
});
@@ -1058,8 +1068,8 @@ struct ST_Envelope {
10581068

10591069
UnaryExecutor::Execute<string_t, string_t>(args.data[0], result, args.size(), [&](const string_t &geom_blob) {
10601070
const auto geom = lstate.Deserialize(geom_blob);
1061-
const auto intersection = geom.get_envelope();
1062-
return lstate.Serialize(result, intersection);
1071+
const auto envelope = geom.get_envelope();
1072+
return lstate.Serialize(result, envelope);
10631073
});
10641074
}
10651075

@@ -1073,7 +1083,7 @@ struct ST_Envelope {
10731083
variant.SetFunction(Execute);
10741084
});
10751085

1076-
func.SetDescription("Returns the envelope of a geometry");
1086+
func.SetDescription("Returns the minimum bounding rectangle of a geometry as a polygon geometry");
10771087
func.SetTag("ext", "spatial");
10781088
func.SetTag("category", "construction");
10791089
});
@@ -1472,7 +1482,7 @@ struct ST_Normalize {
14721482
variant.SetFunction(Execute);
14731483
});
14741484

1475-
func.SetDescription("Returns a normalized representation of the geometry");
1485+
func.SetDescription("Returns the \"normalized\" representation of the geometry");
14761486
func.SetTag("ext", "spatial");
14771487
func.SetTag("category", "construction");
14781488
});

src/spatial/modules/main/spatial_functions_scalar.cpp

+27-3
Original file line numberDiff line numberDiff line change
@@ -1237,9 +1237,8 @@ struct ST_AsSVG {
12371237
// Documentation
12381238
//------------------------------------------------------------------------------------------------------------------
12391239
static constexpr auto DESCRIPTION = R"(
1240-
Convert the geometry into a SVG fragment or path
1241-
12421240
Convert the geometry into a SVG fragment or path
1241+
12431242
The SVG fragment is returned as a string. The fragment is a path element that can be used in an SVG document.
12441243
The second boolean argument specifies whether the path should be relative or absolute.
12451244
The third argument specifies the maximum number of digits to use for the coordinates.
@@ -2067,7 +2066,14 @@ struct ST_Dimension {
20672066
//------------------------------------------------------------------------------------------------------------------
20682067
// Documentation
20692068
//------------------------------------------------------------------------------------------------------------------
2070-
static constexpr auto DESCRIPTION = "Returns the dimension of a geometry.";
2069+
static constexpr auto DESCRIPTION = R"(
2070+
Returns the "topological dimension" of a geometry.
2071+
2072+
- For POINT and MULTIPOINT geometries, returns `0`
2073+
- For LINESTRING and MULTILINESTRING, returns `1`
2074+
- For POLYGON and MULTIPOLYGON, returns `2`
2075+
- For GEOMETRYCOLLECTION, returns the maximum dimension of the contained geometries, or 0 if the collection is empty
2076+
)";
20712077

20722078
static constexpr auto EXAMPLE = R"(
20732079
select st_dimension('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'::geometry);
@@ -2424,12 +2430,23 @@ struct ST_Dump {
24242430
//------------------------------------------------------------------------------------------------------------------
24252431
static constexpr auto DESCRIPTION = R"(
24262432
Dumps a geometry into a list of sub-geometries and their "path" in the original geometry.
2433+
2434+
You can use the `UNNEST(res, recursive := true)` function to explode resulting list of structs into multiple rows.
24272435
)";
24282436

24292437
static constexpr auto EXAMPLE = R"(
24302438
select st_dump('MULTIPOINT(1 2,3 4)'::geometry);
24312439
----
24322440
[{'geom': 'POINT(1 2)', 'path': [0]}, {'geom': 'POINT(3 4)', 'path': [1]}]
2441+
2442+
select unnest(st_dump('MULTIPOINT(1 2,3 4)'::geometry), recursive := true);
2443+
-- ┌─────────────┬─────────┐
2444+
-- │ geom │ path │
2445+
-- │ geometry │ int32[] │
2446+
-- ├─────────────┼─────────┤
2447+
-- │ POINT (1 2) │ [1] │
2448+
-- │ POINT (3 4) │ [2] │
2449+
-- └─────────────┴─────────┘
24332450
)";
24342451

24352452
//------------------------------------------------------------------------------------------------------------------
@@ -2682,6 +2699,13 @@ struct ST_Extent_Approx {
26822699
variant.SetFunction(Execute);
26832700
});
26842701

2702+
func.SetDescription(R"(
2703+
Returns the approximate bounding box of a geometry, if available.
2704+
2705+
This function is only really used internally, and returns the cached bounding box of the geometry if it exists.
2706+
This function may be removed or renamed in the future.
2707+
)");
2708+
26852709
func.SetTag("ext", "spatial");
26862710
func.SetTag("category", "property");
26872711
});

src/spatial/modules/main/spatial_functions_table.cpp

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
#include "duckdb/main/extension_util.hpp"
2+
#include "spatial/geometry/bbox.hpp"
13
#include "spatial/modules/main/spatial_functions.hpp"
24
#include "spatial/spatial_types.hpp"
3-
#include "spatial/geometry/bbox.hpp"
45

5-
#include "duckdb/main/extension_util.hpp"
6+
#include <spatial/util/function_builder.hpp>
67

78
namespace duckdb {
89

@@ -105,6 +106,17 @@ struct ST_GeneratePoints {
105106
return make_uniq<NodeStatistics>(bind_data.count, bind_data.count);
106107
}
107108

109+
//------------------------------------------------------------------------------------------------------------------
110+
// DOCUMENTATION
111+
//------------------------------------------------------------------------------------------------------------------
112+
static constexpr auto DESCRIPTION = R"(
113+
Generates a set of random points within the specified bounding box.
114+
115+
Takes a bounding box (min_x, min_y, max_x, max_y), a count of points to generate, and optionally a seed for the random number generator.
116+
)";
117+
static constexpr auto EXAMPLE =
118+
"SELECT * FROM ST_GeneratePoints({min_x: 0, min_y:0, max_x:10, max_y:10}::BOX_2D, 5, 42);";
119+
108120
//------------------------------------------------------------------------------------------------------------------
109121
// Register
110122
//------------------------------------------------------------------------------------------------------------------
@@ -122,6 +134,7 @@ struct ST_GeneratePoints {
122134
generate_points.arguments = {GeoTypes::BOX_2D(), LogicalType::BIGINT, LogicalType::BIGINT};
123135
set.AddFunction(generate_points);
124136
ExtensionUtil::RegisterFunction(db, set);
137+
FunctionBuilder::AddTableFunctionDocs(db, "ST_GeneratePoints", DESCRIPTION, EXAMPLE, {{"ext", "spatial"}});
125138
}
126139
};
127140

src/spatial/modules/osm/osm_module.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,7 @@ void RegisterOSMModule(DatabaseInstance &db) {
900900
read.table_scan_progress = Progress;
901901

902902
ExtensionUtil::RegisterFunction(db, read);
903-
FunctionBuilder::AddTableFunctionDocs(db, "ST_ReadOSM", DOC_DESCRIPTION, DOC_EXAMPLE);
903+
FunctionBuilder::AddTableFunctionDocs(db, "ST_ReadOSM", DOC_DESCRIPTION, DOC_EXAMPLE, {{"ext", "spatial"}});
904904

905905
// Replacement scan
906906
auto &config = DBConfig::GetConfig(db);

src/spatial/modules/proj/proj_module.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -817,11 +817,11 @@ struct ST_Perimeter_Spheroid {
817817
// Documentation
818818
//------------------------------------------------------------------------------------------------------------------
819819
static constexpr auto DESCRIPTION = R"(
820-
Returns the length of the perimeter in meters using an ellipsoidal model of the earths surface
820+
Returns the length of the perimeter in meters using an ellipsoidal model of the earths surface
821821
822-
The input geometry is assumed to be in the [EPSG:4326](https://en.wikipedia.org/wiki/World_Geodetic_System) coordinate system (WGS84), with [latitude, longitude] axis order and the length is returned in meters. This function uses the [GeographicLib](https://geographiclib.sourceforge.io/) library, calculating the perimeter using an ellipsoidal model of the earth. This is a highly accurate method for calculating the perimeter of a polygon taking the curvature of the earth into account, but is also the slowest.
822+
The input geometry is assumed to be in the [EPSG:4326](https://en.wikipedia.org/wiki/World_Geodetic_System) coordinate system (WGS84), with [latitude, longitude] axis order and the length is returned in meters. This function uses the [GeographicLib](https://geographiclib.sourceforge.io/) library, calculating the perimeter using an ellipsoidal model of the earth. This is a highly accurate method for calculating the perimeter of a polygon taking the curvature of the earth into account, but is also the slowest.
823823
824-
Returns `0.0` for any geometry that is not a `POLYGON`, `MULTIPOLYGON` or `GEOMETRYCOLLECTION` containing polygon geometries.
824+
Returns `0.0` for any geometry that is not a `POLYGON`, `MULTIPOLYGON` or `GEOMETRYCOLLECTION` containing polygon geometries.
825825
)";
826826

827827
// TODO: add example
@@ -953,7 +953,7 @@ struct ST_Length_Spheroid {
953953
static constexpr auto DESCRIPTION = R"(
954954
Returns the length of the input geometry in meters, using an ellipsoidal model of the earth
955955
956-
The input geometry is assumed to be in the [EPSG:4326](https://en.wikipedia.org/wiki/World_Geodetic_System) coordinate system (WGS84), with [latitude, longitude] axis order and the length is returned in square meters. This function uses the [GeographicLib](https://geographiclib.sourceforge.io/) library, calculating the length using an ellipsoidal model of the earth. This is a highly accurate method for calculating the length of a line geometry taking the curvature of the earth into account, but is also the slowest.
956+
The input geometry is assumed to be in the [EPSG:4326](https://en.wikipedia.org/wiki/World_Geodetic_System) coordinate system (WGS84), with [latitude, longitude] axis order and the length is returned in meters. This function uses the [GeographicLib](https://geographiclib.sourceforge.io/) library, calculating the length using an ellipsoidal model of the earth. This is a highly accurate method for calculating the length of a line geometry taking the curvature of the earth into account, but is also the slowest.
957957
958958
Returns `0.0` for any geometry that is not a `LINESTRING`, `MULTILINESTRING` or `GEOMETRYCOLLECTION` containing line geometries.
959959
)";

src/spatial/util/function_builder.cpp

+15-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,19 @@
77

88
namespace duckdb {
99

10-
string FunctionBuilder::RemoveIndentAndTrailingWhitespace(const char *text) {
10+
string FunctionBuilder::RemoveIndentAndTrailingWhitespace(const char *ptr) {
11+
string tmp;
12+
// Replace all tabs with 4 spaces in ptr
13+
for (const char *text = ptr; *text; text++) {
14+
if (*text == '\t') {
15+
tmp.append(" ");
16+
} else {
17+
tmp += *text;
18+
}
19+
}
20+
21+
auto text = tmp.c_str();
22+
1123
string result;
1224
// Skip any empty first newlines if present
1325
while (*text == '\n') {
@@ -157,7 +169,7 @@ void FunctionBuilder::Register(DatabaseInstance &db, const char *name, MacroFunc
157169
}
158170

159171
void FunctionBuilder::AddTableFunctionDocs(DatabaseInstance &db, const char *name, const char *desc,
160-
const char *example) {
172+
const char *example, const unordered_map<string, string> &tags) {
161173

162174
auto &catalog = Catalog::GetSystemCatalog(db);
163175
auto transaction = CatalogTransaction::GetSystemTransaction(db);
@@ -173,6 +185,7 @@ void FunctionBuilder::AddTableFunctionDocs(DatabaseInstance &db, const char *nam
173185
function_description.description = RemoveIndentAndTrailingWhitespace(desc);
174186
function_description.examples.push_back(RemoveIndentAndTrailingWhitespace(example));
175187
func_entry.descriptions.push_back(function_description);
188+
func_entry.tags.insert(tags.begin(), tags.end());
176189
}
177190

178191
} // namespace duckdb

src/spatial/util/function_builder.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ class FunctionBuilder {
2929
static void RegisterMacro(DatabaseInstance &db, const char *name, CALLBACK &&callback);
3030

3131
// TODO:
32-
static void AddTableFunctionDocs(DatabaseInstance &db, const char *name, const char *desc, const char *example);
32+
static void AddTableFunctionDocs(DatabaseInstance &db, const char *name, const char *desc, const char *example,
33+
const unordered_map<string, string> &tags);
3334

3435
static string RemoveIndentAndTrailingWhitespace(const char *str);
3536

0 commit comments

Comments
 (0)