diff --git a/README.md b/README.md
index deff072..fc65382 100644
--- a/README.md
+++ b/README.md
@@ -29,70 +29,69 @@ This extension implements the entire [H3 API](https://h3geo.org/docs/api/indexin
All functions support H3 indexes specified as `UBIGINT` (`uint64`) or `BIGINT` (`int64`),
but the unsigned one is preferred and is returned when the extension can't detect which
-one to use. The unsigned and signed APIs are identical. Many functions also support
-`VARCHAR` H3 index input and output.
+one to use. The unsigned and signed APIs are identical. Most functions also support
+`VARCHAR` H3 index input and output, except as noted below.
### Full list of functions
| Function | Notes | Description
| --: | --- | ---
| `h3_latlng_to_cell` | [u](#fu) | Convert latitude/longitude coordinate to cell ID
-| `h3_cell_to_lat` | [v](#fv) | Convert cell ID to latitude
-| `h3_cell_to_lng` | [v](#fv) | Convert cell ID to longitude
-| `h3_cell_to_latlng` | [v](#fv) | Convert cell ID to latitude/longitude
-| `h3_cell_to_boundary_wkt` | [v](#fv) | Convert cell ID to cell boundary
-| `h3_get_resolution` | [v](#fv) | Get resolution number of cell ID
-| `h3_get_base_cell_number` | [v](#fv) | Get base cell number of cell ID
+| `h3_cell_to_lat` | | Convert cell ID to latitude
+| `h3_cell_to_lng` | | Convert cell ID to longitude
+| `h3_cell_to_latlng` | | Convert cell ID to latitude/longitude
+| `h3_cell_to_boundary_wkt` | | Convert cell ID to cell boundary
+| `h3_get_resolution` | | Get resolution number of cell ID
+| `h3_get_base_cell_number` | | Get base cell number of cell ID
| `h3_string_to_h3` | [u](#fu) | Convert VARCHAR cell ID to UBIGINT
-| `h3_h3_to_string` | [i](#fi) | Convert BIGINT or UBIGINT cell ID to VARCHAR
-| `h3_is_valid_cell` | [v](#fv) | True if this is a valid cell ID
-| `h3_is_res_class_iii` | [v](#fv) | True if the cell's resolution is class III
-| `h3_is_pentagon` | [v](#fv) | True if the cell is a pentagon
-| `h3_get_icosahedron_faces` | [v](#fv) | List of icosahedron face IDs the cell is on
-| `h3_cell_to_parent` | [v](#fv) | Get coarser cell for a cell
-| `h3_cell_to_children` | [v](#fv) | Get finer cells for a cell
-| `h3_cell_to_center_child` | [v](#fv) | Get the center finer cell for a cell
-| `h3_cell_to_child_pos` | [v](#fv) | Get a sub-indexing number for a cell inside a parent
-| `h3_child_pos_to_cell` | [v](#fv) | Convert parent and sub-indexing number to a cell ID
+| `h3_h3_to_string` | | Convert BIGINT or UBIGINT cell ID to VARCHAR
+| `h3_is_valid_cell` | | True if this is a valid cell ID
+| `h3_is_res_class_iii` | | True if the cell's resolution is class III
+| `h3_is_pentagon` | | True if the cell is a pentagon
+| `h3_get_icosahedron_faces` | | List of icosahedron face IDs the cell is on
+| `h3_cell_to_parent` | | Get coarser cell for a cell
+| `h3_cell_to_children` | | Get finer cells for a cell
+| `h3_cell_to_center_child` | | Get the center finer cell for a cell
+| `h3_cell_to_child_pos` | | Get a sub-indexing number for a cell inside a parent
+| `h3_child_pos_to_cell` | | Convert parent and sub-indexing number to a cell ID
| `h3_compact_cells` | [i](#fi) | Convert a set of single-resolution cells to the minimal mixed-resolution set
| `h3_uncompact_cells` | [i](#fi) | Convert a mixed-resolution set to a single-resolution set of cells
-| `h3_grid_disk` | [i](#fi) | Find cells within a grid distance
-| `h3_grid_disk_distances` | [i](#fi) | Find cells within a grid distance, sorted by distance
-| `h3_grid_disk_unsafe` | [i](#fi) | Find cells within a grid distance, with no pentagon distortion
-| `h3_grid_disk_distances_unsafe` | [i](#fi) | Find cells within a grid distance, sorted by distance, with no pentagon distortion
-| `h3_grid_ring_unsafe` | [i](#fi) | Find cells exactly a grid distance away, with no pentagon distortion
-| `h3_grid_path_cells` | [i](#fi) | Find a grid path to connect two cells
-| `h3_grid_distance` | [i](#fi) | Find the grid distance between two cells
-| `h3_cell_to_local_ij` | [i](#fi) | Convert a cell ID to a local I,J coordinate space
-| `h3_local_ij_to_cell` | [i](#fi) | Convert a local I,J coordinate to a cell ID
-| `h3_cell_to_vertex` | [i](#fi) | Get the vertex ID for a cell ID and vertex number
-| `h3_cell_to_vertexes` | [i](#fi) | Get all vertex IDs for a cell ID
-| `h3_vertex_to_lat` | [i](#fi) | Convert a vertex ID to latitude
-| `h3_vertex_to_lng` | [i](#fi) | Convert a vertex ID to longitude
-| `h3_vertex_to_latlng` | [i](#fi) | Convert a vertex ID to latitude/longitude coordinate
-| `h3_is_valid_vertex` | [v](#fv) | True if passed a valid vertex ID
-| `h3_is_valid_directed_edge` | [v](#fv) | True if passed a valid directed edge ID
-| `h3_origin_to_directed_edges` | [i](#fi) | Get all directed edge IDs for a cell ID
-| `h3_directed_edge_to_cells` | [i](#fi) | Convert a directed edge ID to origin/destination cell IDs
-| `h3_get_directed_edge_origin` | [i](#fi) | Convert a directed edge ID to origin cell ID
-| `h3_get_directed_edge_destination` | [i](#fi) | Convert a directed edge ID to destination cell ID
-| `h3_cells_to_directed_edge` | [i](#fi) | Convert an origin/destination pair to directed edge ID
-| `h3_are_neighbor_cells` | [i](#fi) | True if the two cell IDs are directly adjacent
-| `h3_directed_edge_to_boundary_wkt` | [v](#fv) | Convert directed edge ID to linestring WKT
+| `h3_grid_disk` | | Find cells within a grid distance
+| `h3_grid_disk_distances` | | Find cells within a grid distance, sorted by distance
+| `h3_grid_disk_unsafe` | | Find cells within a grid distance, with no pentagon distortion
+| `h3_grid_disk_distances_unsafe` | | Find cells within a grid distance, sorted by distance, with no pentagon distortion
+| `h3_grid_ring_unsafe` | | Find cells exactly a grid distance away, with no pentagon distortion
+| `h3_grid_path_cells` | | Find a grid path to connect two cells
+| `h3_grid_distance` | | Find the grid distance between two cells
+| `h3_cell_to_local_ij` | | Convert a cell ID to a local I,J coordinate space
+| `h3_local_ij_to_cell` | | Convert a local I,J coordinate to a cell ID
+| `h3_cell_to_vertex` | | Get the vertex ID for a cell ID and vertex number
+| `h3_cell_to_vertexes` | | Get all vertex IDs for a cell ID
+| `h3_vertex_to_lat` | | Convert a vertex ID to latitude
+| `h3_vertex_to_lng` | | Convert a vertex ID to longitude
+| `h3_vertex_to_latlng` | | Convert a vertex ID to latitude/longitude coordinate
+| `h3_is_valid_vertex` | | True if passed a valid vertex ID
+| `h3_is_valid_directed_edge` | | True if passed a valid directed edge ID
+| `h3_origin_to_directed_edges` | | Get all directed edge IDs for a cell ID
+| `h3_directed_edge_to_cells` | | Convert a directed edge ID to origin/destination cell IDs
+| `h3_get_directed_edge_origin` | | Convert a directed edge ID to origin cell ID
+| `h3_get_directed_edge_destination` | | Convert a directed edge ID to destination cell ID
+| `h3_cells_to_directed_edge` | | Convert an origin/destination pair to directed edge ID
+| `h3_are_neighbor_cells` | | True if the two cell IDs are directly adjacent
+| `h3_directed_edge_to_boundary_wkt` | | Convert directed edge ID to linestring WKT
| `h3_get_hexagon_area_avg` | | Get average area of a hexagon cell at resolution
-| `h3_cell_area` | [v](#fv) | Get the area of a cell ID
-| `h3_edge_length` | [v](#fv) | Get the length of a directed edge ID
+| `h3_cell_area` | | Get the area of a cell ID
+| `h3_edge_length` | | Get the length of a directed edge ID
| `h3_get_num_cells` | | Get the number of cells at a resolution
| `h3_get_res0_cells` | [u](#fu) | Get all resolution 0 cells
| `h3_get_pentagons` | [u](#fu) | Get all pentagons at a resolution
| `h3_great_circle_distance` | | Compute the great circle distance between two points (haversine)
-| `h3_cells_to_multi_polygon_wkt` | [v](#fv) | Convert a set of cells to multipolygon WKT
+| `h3_cells_to_multi_polygon_wkt` | | Convert a set of cells to multipolygon WKT
| `h3_polygon_wkt_to_cells` | [u](#fu) | Convert polygon WKT to a set of cells
### Notes
-* v: Supports VARCHAR, UBIGINT, and BIGINT input and output.
-* i: Supports UBIGINT and BIGINT input and output. (TODO for these to support VARCHAR too.)
+* i: Supports UBIGINT and BIGINT input and output only, not VARCHAR. (TODO)
* u: Supports UBIGINT output only.
# Alternative download / install
diff --git a/src/h3_directededge.cpp b/src/h3_directededge.cpp
index f1bdad4..b7ab39d 100644
--- a/src/h3_directededge.cpp
+++ b/src/h3_directededge.cpp
@@ -26,6 +26,41 @@ static void DirectedEdgeToCellsFunction(DataChunk &args, ExpressionState &state,
result.Verify(args.size());
}
+static void DirectedEdgeToCellsVarcharFunction(DataChunk &args,
+ ExpressionState &state,
+ Vector &result) {
+ auto result_data = FlatVector::GetData(result);
+ for (idx_t i = 0; i < args.size(); i++) {
+ result_data[i].offset = ListVector::GetListSize(result);
+
+ string edgeInput = args.GetValue(0, i)
+ .DefaultCastAs(LogicalType::VARCHAR)
+ .GetValue();
+
+ H3Index edge;
+ H3Error err0 = stringToH3(edgeInput.c_str(), &edge);
+ if (err0) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ std::vector out(2);
+ H3Error err1 = directedEdgeToCells(edge, out.data());
+ if (err1) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ auto str0 = StringUtil::Format("%llx", out[0]);
+ string_t strAsStr0 = string_t(strdup(str0.c_str()), str0.size());
+ ListVector::PushBack(result, strAsStr0);
+ auto str1 = StringUtil::Format("%llx", out[1]);
+ string_t strAsStr1 = string_t(strdup(str1.c_str()), str1.size());
+ ListVector::PushBack(result, strAsStr1);
+
+ result_data[i].length = 2;
+ }
+ }
+ }
+ result.Verify(args.size());
+}
+
static void OriginToDirectedEdgesFunction(DataChunk &args,
ExpressionState &state,
Vector &result) {
@@ -57,6 +92,46 @@ static void OriginToDirectedEdgesFunction(DataChunk &args,
result.Verify(args.size());
}
+static void OriginToDirectedEdgesVarcharFunction(DataChunk &args,
+ ExpressionState &state,
+ Vector &result) {
+ D_ASSERT(result.GetType().id() == LogicalTypeId::LIST);
+
+ auto result_data = FlatVector::GetData(result);
+ for (idx_t i = 0; i < args.size(); i++) {
+ result_data[i].offset = ListVector::GetListSize(result);
+
+ string originStr = args.GetValue(0, i)
+ .DefaultCastAs(LogicalType::VARCHAR)
+ .GetValue();
+
+ H3Index origin;
+ H3Error err0 = stringToH3(originStr.c_str(), &origin);
+ if (err0) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ int64_t actual = 0;
+ std::vector out(6);
+ H3Error err1 = originToDirectedEdges(origin, out.data());
+ if (err1) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ for (auto val : out) {
+ if (val != H3_NULL) {
+ auto str = StringUtil::Format("%llx", val);
+ string_t strAsStr = string_t(strdup(str.c_str()), str.size());
+ ListVector::PushBack(result, strAsStr);
+ actual++;
+ }
+ }
+
+ result_data[i].length = actual;
+ }
+ }
+ }
+ result.Verify(args.size());
+}
+
static void GetDirectedEdgeOriginFunction(DataChunk &args,
ExpressionState &state,
Vector &result) {
@@ -75,6 +150,33 @@ static void GetDirectedEdgeOriginFunction(DataChunk &args,
});
}
+static void GetDirectedEdgeOriginVarcharFunction(DataChunk &args,
+ ExpressionState &state,
+ Vector &result) {
+ auto &inputs = args.data[0];
+ UnaryExecutor::ExecuteWithNulls(
+ inputs, result, args.size(),
+ [&](string_t inputStr, ValidityMask &mask, idx_t idx) {
+ H3Index input;
+ H3Error err0 = stringToH3(inputStr.GetString().c_str(), &input);
+ if (err0) {
+ mask.SetInvalid(idx);
+ return StringVector::EmptyString(result, 0);
+ } else {
+ H3Index out;
+ H3Error err1 = getDirectedEdgeOrigin(input, &out);
+ if (err1) {
+ mask.SetInvalid(idx);
+ return StringVector::EmptyString(result, 0);
+ } else {
+ auto str = StringUtil::Format("%llx", out);
+ string_t strAsStr = string_t(strdup(str.c_str()), str.size());
+ return StringVector::AddString(result, strAsStr);
+ }
+ }
+ });
+}
+
static void GetDirectedEdgeDestinationFunction(DataChunk &args,
ExpressionState &state,
Vector &result) {
@@ -93,6 +195,33 @@ static void GetDirectedEdgeDestinationFunction(DataChunk &args,
});
}
+static void GetDirectedEdgeDestinationVarcharFunction(DataChunk &args,
+ ExpressionState &state,
+ Vector &result) {
+ auto &inputs = args.data[0];
+ UnaryExecutor::ExecuteWithNulls(
+ inputs, result, args.size(),
+ [&](string_t inputStr, ValidityMask &mask, idx_t idx) {
+ H3Index input;
+ H3Error err0 = stringToH3(inputStr.GetString().c_str(), &input);
+ if (err0) {
+ mask.SetInvalid(idx);
+ return StringVector::EmptyString(result, 0);
+ } else {
+ H3Index out;
+ H3Error err1 = getDirectedEdgeDestination(input, &out);
+ if (err1) {
+ mask.SetInvalid(idx);
+ return StringVector::EmptyString(result, 0);
+ } else {
+ auto str = StringUtil::Format("%llx", out);
+ string_t strAsStr = string_t(strdup(str.c_str()), str.size());
+ return StringVector::AddString(result, strAsStr);
+ }
+ }
+ });
+}
+
static void CellsToDirectedEdgeFunction(DataChunk &args, ExpressionState &state,
Vector &result) {
auto &inputs = args.data[0];
@@ -111,6 +240,36 @@ static void CellsToDirectedEdgeFunction(DataChunk &args, ExpressionState &state,
});
}
+static void CellsToDirectedEdgeVarcharFunction(DataChunk &args,
+ ExpressionState &state,
+ Vector &result) {
+ auto &inputs = args.data[0];
+ auto &inputs2 = args.data[1];
+ BinaryExecutor::ExecuteWithNulls(
+ inputs, inputs2, result, args.size(),
+ [&](string_t inputStr, string_t inputStr2, ValidityMask &mask,
+ idx_t idx) {
+ H3Index input, input2;
+ H3Error err0 = stringToH3(inputStr.GetString().c_str(), &input);
+ H3Error err1 = stringToH3(inputStr2.GetString().c_str(), &input2);
+ if (err0 || err1) {
+ mask.SetInvalid(idx);
+ return StringVector::EmptyString(result, 0);
+ } else {
+ H3Index out;
+ H3Error err = cellsToDirectedEdge(input, input2, &out);
+ if (err) {
+ mask.SetInvalid(idx);
+ return StringVector::EmptyString(result, 0);
+ } else {
+ auto str = StringUtil::Format("%llx", out);
+ string_t strAsStr = string_t(strdup(str.c_str()), str.size());
+ return StringVector::AddString(result, strAsStr);
+ }
+ }
+ });
+}
+
static void AreNeighborCellsFunction(DataChunk &args, ExpressionState &state,
Vector &result) {
auto &inputs = args.data[0];
@@ -129,6 +288,34 @@ static void AreNeighborCellsFunction(DataChunk &args, ExpressionState &state,
});
}
+static void AreNeighborCellsVarcharFunction(DataChunk &args,
+ ExpressionState &state,
+ Vector &result) {
+ auto &inputs = args.data[0];
+ auto &inputs2 = args.data[1];
+ BinaryExecutor::ExecuteWithNulls(
+ inputs, inputs2, result, args.size(),
+ [&](string_t inputStr, string_t inputStr2, ValidityMask &mask,
+ idx_t idx) {
+ H3Index input, input2;
+ H3Error err0 = stringToH3(inputStr.GetString().c_str(), &input);
+ H3Error err1 = stringToH3(inputStr2.GetString().c_str(), &input2);
+ if (err0 || err1) {
+ mask.SetInvalid(idx);
+ return bool(false);
+ } else {
+ int out;
+ H3Error err2 = areNeighborCells(input, input2, &out);
+ if (err2) {
+ mask.SetInvalid(idx);
+ return bool(false);
+ } else {
+ return bool(out);
+ }
+ }
+ });
+}
+
static void IsValidDirectedEdgeVarcharFunction(DataChunk &args,
ExpressionState &state,
Vector &result) {
@@ -210,69 +397,79 @@ static void DirectedEdgeToBoundaryWktVarcharFunction(DataChunk &args,
CreateScalarFunctionInfo H3Functions::GetDirectedEdgeToCellsFunction() {
ScalarFunctionSet funcs("h3_directed_edge_to_cells");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction({LogicalType::UBIGINT},
LogicalType::LIST(LogicalType::UBIGINT),
DirectedEdgeToCellsFunction));
funcs.AddFunction(ScalarFunction({LogicalType::BIGINT},
LogicalType::LIST(LogicalType::UBIGINT),
DirectedEdgeToCellsFunction));
+ funcs.AddFunction(ScalarFunction({LogicalType::VARCHAR},
+ LogicalType::LIST(LogicalType::VARCHAR),
+ DirectedEdgeToCellsVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetOriginToDirectedEdgesFunction() {
ScalarFunctionSet funcs("h3_origin_to_directed_edges");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction({LogicalType::UBIGINT},
LogicalType::LIST(LogicalType::UBIGINT),
OriginToDirectedEdgesFunction));
funcs.AddFunction(ScalarFunction({LogicalType::BIGINT},
LogicalType::LIST(LogicalType::UBIGINT),
OriginToDirectedEdgesFunction));
+ funcs.AddFunction(ScalarFunction({LogicalType::VARCHAR},
+ LogicalType::LIST(LogicalType::VARCHAR),
+ OriginToDirectedEdgesVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetGetDirectedEdgeOriginFunction() {
ScalarFunctionSet funcs("h3_get_directed_edge_origin");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction({LogicalType::UBIGINT}, LogicalType::UBIGINT,
GetDirectedEdgeOriginFunction));
funcs.AddFunction(ScalarFunction({LogicalType::BIGINT}, LogicalType::BIGINT,
GetDirectedEdgeOriginFunction));
+ funcs.AddFunction(ScalarFunction({LogicalType::VARCHAR}, LogicalType::VARCHAR,
+ GetDirectedEdgeOriginVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetGetDirectedEdgeDestinationFunction() {
ScalarFunctionSet funcs("h3_get_directed_edge_destination");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction({LogicalType::UBIGINT}, LogicalType::UBIGINT,
GetDirectedEdgeDestinationFunction));
funcs.AddFunction(ScalarFunction({LogicalType::BIGINT}, LogicalType::BIGINT,
GetDirectedEdgeDestinationFunction));
+ funcs.AddFunction(ScalarFunction({LogicalType::VARCHAR}, LogicalType::VARCHAR,
+ GetDirectedEdgeDestinationVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetCellsToDirectedEdgeFunction() {
ScalarFunctionSet funcs("h3_cells_to_directed_edge");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction({LogicalType::UBIGINT, LogicalType::UBIGINT},
LogicalType::UBIGINT,
CellsToDirectedEdgeFunction));
funcs.AddFunction(ScalarFunction({LogicalType::BIGINT, LogicalType::BIGINT},
LogicalType::BIGINT,
CellsToDirectedEdgeFunction));
+ funcs.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR},
+ LogicalType::VARCHAR,
+ CellsToDirectedEdgeVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetAreNeighborCellsFunction() {
ScalarFunctionSet funcs("h3_are_neighbor_cells");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction({LogicalType::UBIGINT, LogicalType::UBIGINT},
LogicalType::BOOLEAN,
AreNeighborCellsFunction));
funcs.AddFunction(ScalarFunction({LogicalType::BIGINT, LogicalType::BIGINT},
LogicalType::BOOLEAN,
AreNeighborCellsFunction));
+ funcs.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR},
+ LogicalType::BOOLEAN,
+ AreNeighborCellsVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
diff --git a/src/h3_traversal.cpp b/src/h3_traversal.cpp
index 22c88dd..43bfec3 100644
--- a/src/h3_traversal.cpp
+++ b/src/h3_traversal.cpp
@@ -53,6 +53,53 @@ static void GridDiskTmplFunction(DataChunk &args, ExpressionState &state,
result.Verify(args.size());
}
+template
+static void GridDiskTmplVarcharFunction(DataChunk &args, ExpressionState &state,
+ Vector &result) {
+ auto result_data = FlatVector::GetData(result);
+ for (idx_t i = 0; i < args.size(); i++) {
+ result_data[i].offset = ListVector::GetListSize(result);
+
+ string originInput = args.GetValue(0, i)
+ .DefaultCastAs(LogicalType::VARCHAR)
+ .GetValue();
+ int32_t k = args.GetValue(1, i)
+ .DefaultCastAs(LogicalType::INTEGER)
+ .GetValue();
+
+ uint64_t origin;
+ H3Error err0 = stringToH3(originInput.c_str(), &origin);
+ if (err0) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ int64_t sz;
+ H3Error err1 = maxGridDiskSize(k, &sz);
+ if (err1) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ std::vector out(sz);
+ H3Error err2 = Fn::fn(origin, k, out.data());
+ if (err2) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ int64_t actual = 0;
+ for (auto val : out) {
+ if (val != H3_NULL) {
+ auto str = StringUtil::Format("%llx", val);
+ string_t strAsStr = string_t(strdup(str.c_str()), str.size());
+ ListVector::PushBack(result, strAsStr);
+ actual++;
+ }
+ }
+
+ result_data[i].length = actual;
+ }
+ }
+ }
+ }
+ result.Verify(args.size());
+}
+
struct GridDiskDistancesOperator {
static H3Error fn(H3Index origin, int32_t k, H3Index *out,
int32_t *distancesOut) {
@@ -121,6 +168,63 @@ static void GridDiskDistancesTmplFunction(DataChunk &args,
result.Verify(args.size());
}
+template
+static void GridDiskDistancesTmplVarcharFunction(DataChunk &args,
+ ExpressionState &state,
+ Vector &result) {
+ auto result_data = FlatVector::GetData(result);
+ for (idx_t i = 0; i < args.size(); i++) {
+ result_data[i].offset = ListVector::GetListSize(result);
+
+ string originInput = args.GetValue(0, i)
+ .DefaultCastAs(LogicalType::VARCHAR)
+ .GetValue();
+ int32_t k = args.GetValue(1, i)
+ .DefaultCastAs(LogicalType::INTEGER)
+ .GetValue();
+
+ H3Index origin;
+ H3Error err0 = stringToH3(originInput.c_str(), &origin);
+ if (err0) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ int64_t sz;
+ H3Error err1 = maxGridDiskSize(k, &sz);
+ if (err1) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ std::vector out(sz);
+ std::vector distancesOut(sz);
+ H3Error err2 = Fn::fn(origin, k, out.data(), distancesOut.data());
+ if (err2) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ // Reorganize the results similar to H3-Java sorted list of list of
+ // indexes std vector of duckdb vector
+ std::vector> results(k + 1);
+ for (idx_t j = 0; j < out.size(); j++) {
+ if (out[j] != H3_NULL) {
+ auto str = StringUtil::Format("%llx", out[j]);
+ string_t strAsStr = string_t(strdup(str.c_str()), str.size());
+ results[distancesOut[j]].push_back(strAsStr);
+ }
+ }
+
+ int64_t actual = 0;
+ for (auto val : results) {
+ ListVector::PushBack(result,
+ Value::LIST(LogicalType::VARCHAR, val));
+ actual++;
+ }
+
+ result_data[i].length = actual;
+ }
+ }
+ }
+ }
+ result.Verify(args.size());
+}
+
static void GridRingUnsafeFunction(DataChunk &args, ExpressionState &state,
Vector &result) {
auto result_data = FlatVector::GetData(result);
@@ -153,6 +257,47 @@ static void GridRingUnsafeFunction(DataChunk &args, ExpressionState &state,
result.Verify(args.size());
}
+static void GridRingUnsafeVarcharFunction(DataChunk &args,
+ ExpressionState &state,
+ Vector &result) {
+ auto result_data = FlatVector::GetData(result);
+ for (idx_t i = 0; i < args.size(); i++) {
+ result_data[i].offset = ListVector::GetListSize(result);
+
+ string originInput = args.GetValue(0, i)
+ .DefaultCastAs(LogicalType::VARCHAR)
+ .GetValue();
+ int32_t k = args.GetValue(1, i)
+ .DefaultCastAs(LogicalType::INTEGER)
+ .GetValue();
+ H3Index origin;
+ H3Error err0 = stringToH3(originInput.c_str(), &origin);
+ if (err0) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ int64_t sz = k == 0 ? 1 : 6 * k;
+ std::vector out(sz);
+ H3Error err1 = gridRingUnsafe(origin, k, out.data());
+ if (err1) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ int64_t actual = 0;
+ for (auto val : out) {
+ if (val != H3_NULL) {
+ auto str = StringUtil::Format("%llx", val);
+ string_t strAsStr = string_t(strdup(str.c_str()), str.size());
+ ListVector::PushBack(result, strAsStr);
+ actual++;
+ }
+ }
+
+ result_data[i].length = actual;
+ }
+ }
+ }
+ result.Verify(args.size());
+}
+
static void GridPathCellsFunction(DataChunk &args, ExpressionState &state,
Vector &result) {
auto result_data = FlatVector::GetData(result);
@@ -191,6 +336,54 @@ static void GridPathCellsFunction(DataChunk &args, ExpressionState &state,
result.Verify(args.size());
}
+static void GridPathCellsVarcharFunction(DataChunk &args,
+ ExpressionState &state,
+ Vector &result) {
+ auto result_data = FlatVector::GetData(result);
+ for (idx_t i = 0; i < args.size(); i++) {
+ result_data[i].offset = ListVector::GetListSize(result);
+
+ string originInput = args.GetValue(0, i)
+ .DefaultCastAs(LogicalType::VARCHAR)
+ .GetValue();
+ string destinationInput = args.GetValue(1, i)
+ .DefaultCastAs(LogicalType::VARCHAR)
+ .GetValue();
+
+ H3Index origin, destination;
+ H3Error err0 = stringToH3(originInput.c_str(), &origin);
+ H3Error err1 = stringToH3(destinationInput.c_str(), &destination);
+ if (err0 || err1) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ int64_t sz;
+ H3Error err2 = gridPathCellsSize(origin, destination, &sz);
+ if (err2) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ std::vector out(sz);
+ H3Error err3 = gridPathCells(origin, destination, out.data());
+ if (err3) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ int64_t actual = 0;
+ for (auto val : out) {
+ if (val != H3_NULL) {
+ auto str = StringUtil::Format("%llx", val);
+ string_t strAsStr = string_t(strdup(str.c_str()), str.size());
+ ListVector::PushBack(result, strAsStr);
+ actual++;
+ }
+ }
+
+ result_data[i].length = actual;
+ }
+ }
+ }
+ }
+ result.Verify(args.size());
+}
+
static void GridDistanceFunction(DataChunk &args, ExpressionState &state,
Vector &result) {
auto &inputs = args.data[0];
@@ -210,6 +403,34 @@ static void GridDistanceFunction(DataChunk &args, ExpressionState &state,
});
}
+static void GridDistanceVarcharFunction(DataChunk &args, ExpressionState &state,
+ Vector &result) {
+ auto &inputs = args.data[0];
+ auto &inputs2 = args.data[1];
+ BinaryExecutor::ExecuteWithNulls(
+ inputs, inputs2, result, args.size(),
+ [&](string_t originInput, string_t destinationInput, ValidityMask &mask,
+ idx_t idx) {
+ H3Index origin, destination;
+ H3Error err0 = stringToH3(originInput.GetString().c_str(), &origin);
+ H3Error err1 =
+ stringToH3(destinationInput.GetString().c_str(), &destination);
+ if (err0 || err1) {
+ mask.SetInvalid(idx);
+ return int64_t(0);
+ } else {
+ int64_t distance;
+ H3Error err = gridDistance(origin, destination, &distance);
+ if (err) {
+ mask.SetInvalid(idx);
+ return int64_t(0);
+ } else {
+ return distance;
+ }
+ }
+ });
+}
+
static void CellToLocalIjFunction(DataChunk &args, ExpressionState &state,
Vector &result) {
auto result_data = FlatVector::GetData(result);
@@ -237,6 +458,41 @@ static void CellToLocalIjFunction(DataChunk &args, ExpressionState &state,
result.Verify(args.size());
}
+static void CellToLocalIjVarcharFunction(DataChunk &args,
+ ExpressionState &state,
+ Vector &result) {
+ auto result_data = FlatVector::GetData(result);
+ for (idx_t i = 0; i < args.size(); i++) {
+ result_data[i].offset = ListVector::GetListSize(result);
+
+ string originInput = args.GetValue(0, i)
+ .DefaultCastAs(LogicalType::VARCHAR)
+ .GetValue();
+ string cellInput = args.GetValue(1, i)
+ .DefaultCastAs(LogicalType::VARCHAR)
+ .GetValue();
+ uint32_t mode = 0; // TODO: Expose mode to the user when applicable
+
+ H3Index origin, cell;
+ H3Error err0 = stringToH3(originInput.c_str(), &origin);
+ H3Error err1 = stringToH3(cellInput.c_str(), &cell);
+ if (err0 || err1) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ CoordIJ out;
+ H3Error err2 = cellToLocalIj(origin, cell, mode, &out);
+ if (err2) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ ListVector::PushBack(result, Value::INTEGER(out.i));
+ ListVector::PushBack(result, Value::INTEGER(out.j));
+ result_data[i].length = 2;
+ }
+ }
+ }
+ result.Verify(args.size());
+}
+
static void LocalIjToCellFunction(DataChunk &args, ExpressionState &state,
Vector &result) {
auto &inputs = args.data[0];
@@ -259,21 +515,55 @@ static void LocalIjToCellFunction(DataChunk &args, ExpressionState &state,
});
}
+static void LocalIjToCellVarcharFunction(DataChunk &args,
+ ExpressionState &state,
+ Vector &result) {
+ auto &inputs = args.data[0];
+ auto &inputs2 = args.data[1];
+ auto &inputs3 = args.data[2];
+ TernaryExecutor::ExecuteWithNulls(
+ inputs, inputs2, inputs3, result, args.size(),
+ [&](string_t input, int32_t i, int32_t j, ValidityMask &mask, idx_t idx) {
+ H3Index origin;
+ H3Error err0 = stringToH3(input.GetString().c_str(), &origin);
+ if (err0) {
+ mask.SetInvalid(idx);
+ return StringVector::EmptyString(result, 0);
+ } else {
+ uint32_t mode = 0; // TODO: Expose mode to the user when applicable
+
+ CoordIJ coordIJ{.i = i, .j = j};
+ H3Index out;
+ H3Error err1 = localIjToCell(origin, &coordIJ, mode, &out);
+ if (err1) {
+ mask.SetInvalid(idx);
+ return StringVector::EmptyString(result, 0);
+ } else {
+ auto str = StringUtil::Format("%llx", out);
+ string_t strAsStr = string_t(strdup(str.c_str()), str.size());
+ return StringVector::AddString(result, strAsStr);
+ }
+ }
+ });
+}
+
CreateScalarFunctionInfo H3Functions::GetGridDiskFunction() {
ScalarFunctionSet funcs("h3_grid_disk");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction({LogicalType::UBIGINT, LogicalType::INTEGER},
LogicalType::LIST(LogicalType::UBIGINT),
GridDiskTmplFunction));
funcs.AddFunction(ScalarFunction({LogicalType::BIGINT, LogicalType::INTEGER},
LogicalType::LIST(LogicalType::BIGINT),
GridDiskTmplFunction));
+ funcs.AddFunction(
+ ScalarFunction({LogicalType::VARCHAR, LogicalType::INTEGER},
+ LogicalType::LIST(LogicalType::VARCHAR),
+ GridDiskTmplVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetGridDiskDistancesFunction() {
ScalarFunctionSet funcs("h3_grid_disk_distances");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(
ScalarFunction({LogicalType::UBIGINT, LogicalType::INTEGER},
LogicalType::LIST(LogicalType::LIST(LogicalType::UBIGINT)),
@@ -282,12 +572,15 @@ CreateScalarFunctionInfo H3Functions::GetGridDiskDistancesFunction() {
ScalarFunction({LogicalType::BIGINT, LogicalType::INTEGER},
LogicalType::LIST(LogicalType::LIST(LogicalType::BIGINT)),
GridDiskDistancesTmplFunction));
+ funcs.AddFunction(ScalarFunction(
+ {LogicalType::VARCHAR, LogicalType::INTEGER},
+ LogicalType::LIST(LogicalType::LIST(LogicalType::VARCHAR)),
+ GridDiskDistancesTmplVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetGridDiskUnsafeFunction() {
ScalarFunctionSet funcs("h3_grid_disk_unsafe");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(
ScalarFunction({LogicalType::UBIGINT, LogicalType::INTEGER},
LogicalType::LIST(LogicalType::UBIGINT),
@@ -296,12 +589,15 @@ CreateScalarFunctionInfo H3Functions::GetGridDiskUnsafeFunction() {
ScalarFunction({LogicalType::BIGINT, LogicalType::INTEGER},
LogicalType::LIST(LogicalType::BIGINT),
GridDiskTmplFunction));
+ funcs.AddFunction(
+ ScalarFunction({LogicalType::VARCHAR, LogicalType::INTEGER},
+ LogicalType::LIST(LogicalType::VARCHAR),
+ GridDiskTmplVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetGridDiskDistancesUnsafeFunction() {
ScalarFunctionSet funcs("h3_grid_disk_distances_unsafe");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction(
{LogicalType::UBIGINT, LogicalType::INTEGER},
LogicalType::LIST(LogicalType::LIST(LogicalType::UBIGINT)),
@@ -310,12 +606,15 @@ CreateScalarFunctionInfo H3Functions::GetGridDiskDistancesUnsafeFunction() {
{LogicalType::BIGINT, LogicalType::INTEGER},
LogicalType::LIST(LogicalType::LIST(LogicalType::BIGINT)),
GridDiskDistancesTmplFunction));
+ funcs.AddFunction(ScalarFunction(
+ {LogicalType::VARCHAR, LogicalType::INTEGER},
+ LogicalType::LIST(LogicalType::LIST(LogicalType::VARCHAR)),
+ GridDiskDistancesTmplVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetGridDiskDistancesSafeFunction() {
ScalarFunctionSet funcs("h3_grid_disk_distances_safe");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction(
{LogicalType::UBIGINT, LogicalType::INTEGER},
LogicalType::LIST(LogicalType::LIST(LogicalType::UBIGINT)),
@@ -324,64 +623,78 @@ CreateScalarFunctionInfo H3Functions::GetGridDiskDistancesSafeFunction() {
{LogicalType::BIGINT, LogicalType::INTEGER},
LogicalType::LIST(LogicalType::LIST(LogicalType::BIGINT)),
GridDiskDistancesTmplFunction));
+ funcs.AddFunction(ScalarFunction(
+ {LogicalType::VARCHAR, LogicalType::INTEGER},
+ LogicalType::LIST(LogicalType::LIST(LogicalType::VARCHAR)),
+ GridDiskDistancesTmplVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetGridRingUnsafeFunction() {
ScalarFunctionSet funcs("h3_grid_ring_unsafe");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction({LogicalType::UBIGINT, LogicalType::INTEGER},
LogicalType::LIST(LogicalType::UBIGINT),
GridRingUnsafeFunction));
funcs.AddFunction(ScalarFunction({LogicalType::BIGINT, LogicalType::INTEGER},
LogicalType::LIST(LogicalType::BIGINT),
GridRingUnsafeFunction));
+ funcs.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::INTEGER},
+ LogicalType::LIST(LogicalType::VARCHAR),
+ GridRingUnsafeVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetGridPathCellsFunction() {
ScalarFunctionSet funcs("h3_grid_path_cells");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction({LogicalType::UBIGINT, LogicalType::UBIGINT},
LogicalType::LIST(LogicalType::UBIGINT),
GridPathCellsFunction));
funcs.AddFunction(ScalarFunction({LogicalType::BIGINT, LogicalType::BIGINT},
LogicalType::LIST(LogicalType::BIGINT),
GridPathCellsFunction));
+ funcs.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR},
+ LogicalType::LIST(LogicalType::VARCHAR),
+ GridPathCellsVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetGridDistanceFunction() {
ScalarFunctionSet funcs("h3_grid_distance");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction({LogicalType::UBIGINT, LogicalType::UBIGINT},
LogicalType::BIGINT, GridDistanceFunction));
funcs.AddFunction(ScalarFunction({LogicalType::BIGINT, LogicalType::BIGINT},
LogicalType::BIGINT, GridDistanceFunction));
+ funcs.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR},
+ LogicalType::BIGINT,
+ GridDistanceVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetCellToLocalIjFunction() {
ScalarFunctionSet funcs("h3_cell_to_local_ij");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction({LogicalType::UBIGINT, LogicalType::UBIGINT},
LogicalType::LIST(LogicalType::INTEGER),
CellToLocalIjFunction));
funcs.AddFunction(ScalarFunction({LogicalType::BIGINT, LogicalType::BIGINT},
LogicalType::LIST(LogicalType::INTEGER),
CellToLocalIjFunction));
+ funcs.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR},
+ LogicalType::LIST(LogicalType::VARCHAR),
+ CellToLocalIjVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetLocalIjToCellFunction() {
ScalarFunctionSet funcs("h3_local_ij_to_cell");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction(
{LogicalType::UBIGINT, LogicalType::INTEGER, LogicalType::INTEGER},
LogicalType::UBIGINT, LocalIjToCellFunction));
funcs.AddFunction(ScalarFunction(
{LogicalType::BIGINT, LogicalType::INTEGER, LogicalType::INTEGER},
LogicalType::BIGINT, LocalIjToCellFunction));
+ funcs.AddFunction(ScalarFunction(
+ {LogicalType::VARCHAR, LogicalType::INTEGER, LogicalType::INTEGER},
+ LogicalType::VARCHAR, LocalIjToCellVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
diff --git a/src/h3_vertex.cpp b/src/h3_vertex.cpp
index a8b662e..213ece3 100644
--- a/src/h3_vertex.cpp
+++ b/src/h3_vertex.cpp
@@ -21,6 +21,34 @@ static void CellToVertexFunction(DataChunk &args, ExpressionState &state,
});
}
+static void CellToVertexVarcharFunction(DataChunk &args, ExpressionState &state,
+ Vector &result) {
+ auto &inputs = args.data[0];
+ auto &inputs2 = args.data[1];
+ BinaryExecutor::ExecuteWithNulls(
+ inputs, inputs2, result, args.size(),
+ [&](string_t cellInput, int32_t vertexNum, ValidityMask &mask,
+ idx_t idx) {
+ H3Index cell;
+ H3Error err0 = stringToH3(cellInput.GetString().c_str(), &cell);
+ if (err0) {
+ mask.SetInvalid(idx);
+ return StringVector::EmptyString(result, 0);
+ } else {
+ H3Index vertex;
+ H3Error err1 = cellToVertex(cell, vertexNum, &vertex);
+ if (err1) {
+ mask.SetInvalid(idx);
+ return StringVector::EmptyString(result, 0);
+ } else {
+ auto str = StringUtil::Format("%llx", vertex);
+ string_t strAsStr = string_t(strdup(str.c_str()), str.size());
+ return StringVector::AddString(result, strAsStr);
+ }
+ }
+ });
+}
+
static void CellToVertexesFunction(DataChunk &args, ExpressionState &state,
Vector &result) {
result.SetVectorType(VectorType::FLAT_VECTOR);
@@ -60,6 +88,54 @@ static void CellToVertexesFunction(DataChunk &args, ExpressionState &state,
}
}
+static void CellToVertexesVarcharFunction(DataChunk &args,
+ ExpressionState &state,
+ Vector &result) {
+ result.SetVectorType(VectorType::FLAT_VECTOR);
+ auto &result_validity = FlatVector::Validity(result);
+ auto result_data = FlatVector::GetData(result);
+ idx_t offset = 0;
+ for (idx_t i = 0; i < args.size(); i++) {
+ result_data[i].offset = offset;
+
+ string cellInput = args.GetValue(0, i)
+ .DefaultCastAs(LogicalType::VARCHAR)
+ .GetValue();
+
+ H3Index cell;
+ H3Error err0 = stringToH3(cellInput.c_str(), &cell);
+ if (err0) {
+ result_validity.SetInvalid(i);
+ result_data[i].length = 0;
+ } else {
+ int64_t actual = 0;
+ std::vector out(6);
+ H3Error err = cellToVertexes(cell, out.data());
+ if (err) {
+ result_validity.SetInvalid(i);
+ result_data[i].length = 0;
+ } else {
+ for (auto val : out) {
+ if (val != H3_NULL) {
+ auto str = StringUtil::Format("%llx", val);
+ string_t strAsStr = string_t(strdup(str.c_str()), str.size());
+ ListVector::PushBack(result, strAsStr);
+ actual++;
+ }
+ }
+
+ result_data[i].length = actual;
+ }
+ offset += actual;
+ }
+ }
+ result.Verify(args.size());
+
+ if (args.AllConstant()) {
+ result.SetVectorType(VectorType::CONSTANT_VECTOR);
+ }
+}
+
static void VertexToLatFunction(DataChunk &args, ExpressionState &state,
Vector &result) {
auto &inputs = args.data[0];
@@ -77,6 +153,30 @@ static void VertexToLatFunction(DataChunk &args, ExpressionState &state,
});
}
+static void VertexToLatVarcharFunction(DataChunk &args, ExpressionState &state,
+ Vector &result) {
+ auto &inputs = args.data[0];
+ UnaryExecutor::ExecuteWithNulls(
+ inputs, result, args.size(),
+ [&](string_t vertexInput, ValidityMask &mask, idx_t idx) {
+ H3Index vertex;
+ H3Error err0 = stringToH3(vertexInput.GetString().c_str(), &vertex);
+ if (err0) {
+ mask.SetInvalid(idx);
+ return .0;
+ } else {
+ LatLng latLng = {.lat = 0, .lng = 0};
+ H3Error err1 = vertexToLatLng(vertex, &latLng);
+ if (err1) {
+ mask.SetInvalid(idx);
+ return .0;
+ } else {
+ return radsToDegs(latLng.lat);
+ }
+ }
+ });
+}
+
static void VertexToLngFunction(DataChunk &args, ExpressionState &state,
Vector &result) {
auto &inputs = args.data[0];
@@ -94,6 +194,30 @@ static void VertexToLngFunction(DataChunk &args, ExpressionState &state,
});
}
+static void VertexToLngVarcharFunction(DataChunk &args, ExpressionState &state,
+ Vector &result) {
+ auto &inputs = args.data[0];
+ UnaryExecutor::ExecuteWithNulls(
+ inputs, result, args.size(),
+ [&](string_t vertexInput, ValidityMask &mask, idx_t idx) {
+ H3Index vertex;
+ H3Error err0 = stringToH3(vertexInput.GetString().c_str(), &vertex);
+ if (err0) {
+ mask.SetInvalid(idx);
+ return .0;
+ } else {
+ LatLng latLng = {.lat = 0, .lng = 0};
+ H3Error err1 = vertexToLatLng(vertex, &latLng);
+ if (err1) {
+ mask.SetInvalid(idx);
+ return .0;
+ } else {
+ return radsToDegs(latLng.lng);
+ }
+ }
+ });
+}
+
static void VertexToLatLngFunction(DataChunk &args, ExpressionState &state,
Vector &result) {
auto result_data = FlatVector::GetData(result);
@@ -114,6 +238,35 @@ static void VertexToLatLngFunction(DataChunk &args, ExpressionState &state,
result.Verify(args.size());
}
+static void VertexToLatLngVarcharFunction(DataChunk &args,
+ ExpressionState &state,
+ Vector &result) {
+ auto result_data = FlatVector::GetData(result);
+ for (idx_t i = 0; i < args.size(); i++) {
+ result_data[i].offset = ListVector::GetListSize(result);
+
+ string vertexInput = args.GetValue(0, i)
+ .DefaultCastAs(LogicalType::VARCHAR)
+ .GetValue();
+ H3Index vertex;
+ H3Error err0 = stringToH3(vertexInput.c_str(), &vertex);
+ if (err0) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ LatLng latLng;
+ H3Error err1 = vertexToLatLng(vertex, &latLng);
+ if (err1) {
+ result.SetValue(i, Value(LogicalType::SQLNULL));
+ } else {
+ ListVector::PushBack(result, radsToDegs(latLng.lat));
+ ListVector::PushBack(result, radsToDegs(latLng.lng));
+ result_data[i].length = 2;
+ }
+ }
+ }
+ result.Verify(args.size());
+}
+
static void IsValidVertexVarcharFunction(DataChunk &args,
ExpressionState &state,
Vector &result) {
@@ -139,55 +292,63 @@ static void IsValidVertexFunction(DataChunk &args, ExpressionState &state,
CreateScalarFunctionInfo H3Functions::GetCellToVertexFunction() {
ScalarFunctionSet funcs("h3_cell_to_vertex");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction({LogicalType::UBIGINT, LogicalType::INTEGER},
LogicalType::UBIGINT, CellToVertexFunction));
funcs.AddFunction(ScalarFunction({LogicalType::BIGINT, LogicalType::INTEGER},
LogicalType::BIGINT, CellToVertexFunction));
+ funcs.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::INTEGER},
+ LogicalType::VARCHAR,
+ CellToVertexVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetCellToVertexesFunction() {
ScalarFunctionSet funcs("h3_cell_to_vertexes");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction({LogicalType::UBIGINT},
LogicalType::LIST(LogicalType::UBIGINT),
CellToVertexesFunction));
funcs.AddFunction(ScalarFunction({LogicalType::BIGINT},
LogicalType::LIST(LogicalType::BIGINT),
CellToVertexesFunction));
+ funcs.AddFunction(ScalarFunction({LogicalType::VARCHAR},
+ LogicalType::LIST(LogicalType::VARCHAR),
+ CellToVertexesVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetVertexToLatFunction() {
ScalarFunctionSet funcs("h3_vertex_to_lat");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction({LogicalType::UBIGINT}, LogicalType::DOUBLE,
VertexToLatFunction));
funcs.AddFunction(ScalarFunction({LogicalType::BIGINT}, LogicalType::DOUBLE,
VertexToLatFunction));
+ funcs.AddFunction(ScalarFunction({LogicalType::VARCHAR}, LogicalType::DOUBLE,
+ VertexToLatVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetVertexToLngFunction() {
ScalarFunctionSet funcs("h3_vertex_to_lng");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction({LogicalType::UBIGINT}, LogicalType::DOUBLE,
VertexToLngFunction));
funcs.AddFunction(ScalarFunction({LogicalType::BIGINT}, LogicalType::DOUBLE,
VertexToLngFunction));
+ funcs.AddFunction(ScalarFunction({LogicalType::VARCHAR}, LogicalType::DOUBLE,
+ VertexToLngVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
CreateScalarFunctionInfo H3Functions::GetVertexToLatLngFunction() {
ScalarFunctionSet funcs("h3_vertex_to_latlng");
- // TODO: VARCHAR variant of this function
funcs.AddFunction(ScalarFunction({LogicalType::UBIGINT},
LogicalType::LIST(LogicalType::DOUBLE),
VertexToLatLngFunction));
funcs.AddFunction(ScalarFunction({LogicalType::BIGINT},
LogicalType::LIST(LogicalType::DOUBLE),
VertexToLatLngFunction));
+ funcs.AddFunction(ScalarFunction({LogicalType::VARCHAR},
+ LogicalType::LIST(LogicalType::DOUBLE),
+ VertexToLatLngVarcharFunction));
return CreateScalarFunctionInfo(funcs);
}
diff --git a/test/sql/h3/h3_functions_directededge.test b/test/sql/h3/h3_functions_directededge.test
index 8888ec7..3d9685a 100644
--- a/test/sql/h3/h3_functions_directededge.test
+++ b/test/sql/h3/h3_functions_directededge.test
@@ -129,3 +129,43 @@ query I
SELECT h3_directed_edge_to_boundary_wkt('115283473fffffff')
----
POLYGON ((-122.037735 37.420129, -122.090429 37.337556, -122.037735 37.420129))
+
+query I
+SELECT h3_origin_to_directed_edges('85283473fffffff')
+----
+[115283473fffffff, 125283473fffffff, 135283473fffffff, 145283473fffffff, 155283473fffffff, 165283473fffffff]
+
+query I
+SELECT h3_directed_edge_to_cells('165283473fffffff')
+----
+[85283473fffffff, 85283447fffffff]
+
+query I
+SELECT h3_directed_edge_to_cells('0')
+----
+NULL
+
+query I
+SELECT h3_get_directed_edge_origin('165283473fffffff')
+----
+85283473fffffff
+
+query I
+SELECT h3_get_directed_edge_destination('165283473fffffff')
+----
+85283447fffffff
+
+query I
+SELECT h3_cells_to_directed_edge('85283473fffffff', '85283447fffffff')
+----
+165283473fffffff
+
+query I
+SELECT h3_are_neighbor_cells('85283473fffffff', '85283447fffffff')
+----
+true
+
+query I
+SELECT h3_are_neighbor_cells('85283473fffffff', '85283443fffffff')
+----
+false
diff --git a/test/sql/h3/h3_functions_traversal.test b/test/sql/h3/h3_functions_traversal.test
index 42fc84f..51ef12d 100644
--- a/test/sql/h3/h3_functions_traversal.test
+++ b/test/sql/h3/h3_functions_traversal.test
@@ -120,6 +120,66 @@ select h3_grid_ring_unsafe(586265647244115967::bigint, 1);
----
[586267846267371519, 586260699441790975, 586244756523188223, 586245306279002111, 586266196999929855, 586264547732488191]
+query I
+select h3_grid_disk('822d57fffffffff', 1);
+----
+[822d57fffffffff, 822d0ffffffffff, 822c27fffffffff, 822c2ffffffffff, 822d5ffffffffff, 822d47fffffffff, 822d77fffffffff]
+
+query I
+select h3_grid_disk_distances('822d57fffffffff', 1);
+----
+[[822d57fffffffff], [822d0ffffffffff, 822c27fffffffff, 822c2ffffffffff, 822d5ffffffffff, 822d47fffffffff, 822d77fffffffff]]
+
+query I
+select h3_grid_disk('8408001ffffffff', 1);
+----
+[840800bffffffff, 840800dffffffff, 8408001ffffffff, 8408005ffffffff, 8408007ffffffff, 8408009ffffffff]
+
+query I
+select h3_grid_disk('8408001ffffffff', -1);
+----
+NULL
+
+query I
+select h3_grid_disk_distances('8408001ffffffff', 1);
+----
+[[8408001ffffffff], [840800bffffffff, 840800dffffffff, 8408005ffffffff, 8408007ffffffff, 8408009ffffffff]]
+
+query I
+select h3_grid_disk_unsafe('822d57fffffffff', 1);
+----
+[822d57fffffffff, 822d0ffffffffff, 822c27fffffffff, 822c2ffffffffff, 822d5ffffffffff, 822d47fffffffff, 822d77fffffffff]
+
+query I
+select h3_grid_disk_distances_unsafe('822d57fffffffff', 1);
+----
+[[822d57fffffffff], [822d0ffffffffff, 822c27fffffffff, 822c2ffffffffff, 822d5ffffffffff, 822d47fffffffff, 822d77fffffffff]]
+
+query I
+select h3_grid_disk_unsafe('8408001ffffffff', 1);
+----
+NULL
+
+query I
+select h3_grid_disk_distances_unsafe('8408001ffffffff', 2);
+----
+NULL
+
+query I
+select h3_grid_disk_distances_safe('8408001ffffffff', 2);
+----
+[[8408001ffffffff], [8408007ffffffff, 840800bffffffff, 8408005ffffffff, 8408009ffffffff, 840800dffffffff], [8408063ffffffff, 840803dffffffff, 8408047ffffffff, 8408057ffffffff, 840802bffffffff, 840806bffffffff, 8408055ffffffff, 8408029ffffffff, 8408039ffffffff, 8408043ffffffff]]
+
+query I
+select h3_grid_ring_unsafe('8408001ffffffff', 1);
+----
+NULL
+
+query I
+select h3_grid_ring_unsafe('822d57fffffffff', 1);
+----
+[822d77fffffffff, 822d0ffffffffff, 822c27fffffffff, 822c2ffffffffff, 822d5ffffffffff, 822d47fffffffff]
+
query I
select h3_grid_path_cells(605035864166236159::ubigint, 605034941150920703::ubigint);
----
@@ -140,6 +200,21 @@ select h3_grid_path_cells(605035864166236159::bigint, 0::bigint);
----
NULL
+query I
+select h3_grid_path_cells('86584e9afffffff', '8658412c7ffffff');
+----
+[86584e9afffffff, 86584e91fffffff, 86584e907ffffff, 86584e92fffffff, 8658412d7ffffff, 8658412c7ffffff]
+
+query I
+select h3_grid_path_cells('86584e9afffffff', '0');
+----
+NULL
+
+query I
+select h3_grid_path_cells('0', '86584e9afffffff');
+----
+NULL
+
query I
select h3_grid_distance(605035864166236159::ubigint, 605034941150920703::ubigint);
----
@@ -160,6 +235,21 @@ select h3_grid_distance(605035864166236159::bigint, 0::bigint);
----
NULL
+query I
+select h3_grid_distance('86584e9afffffff', '8658412c7ffffff');
+----
+5
+
+query I
+select h3_grid_distance('86584e9afffffff', '0');
+----
+NULL
+
+query I
+select h3_grid_distance('0', '86584e9afffffff');
+----
+NULL
+
query I
select h3_cell_to_local_ij(605034941285138431::ubigint, 605034941285138431::ubigint);
----
@@ -199,3 +289,28 @@ query I
select h3_local_ij_to_cell(605034941285138431::bigint, -1230000, -177);
----
NULL
+
+query I
+select h3_cell_to_local_ij('8658412cfffffff', '8658412cfffffff');
+----
+[-123, -177]
+
+query I
+select h3_cell_to_local_ij('8658412cfffffff', '0');
+----
+NULL
+
+query I
+select h3_cell_to_local_ij('8658412cfffffff', 'abc');
+----
+NULL
+
+query I
+select h3_local_ij_to_cell('8658412cfffffff', -123, -177);
+----
+8658412cfffffff
+
+query I
+select h3_local_ij_to_cell('8658412cfffffff', -1230000, -177);
+----
+NULL
diff --git a/test/sql/h3/h3_functions_vertex.test b/test/sql/h3/h3_functions_vertex.test
index 187f707..1d26ee6 100644
--- a/test/sql/h3/h3_functions_vertex.test
+++ b/test/sql/h3/h3_functions_vertex.test
@@ -99,3 +99,38 @@ query I
SELECT h3_vertex_to_lng(cast(h3_string_to_h3('2222597fffffffff') as bigint));
----
88.57496213785487
+
+query I
+SELECT h3_cell_to_vertexes('823d6ffffffffff');
+----
+[2222597fffffffff, 2523d47fffffffff, 2423d47fffffffff, 21224b7fffffffff, 20224b7fffffffff, 2322597fffffffff]
+
+query I
+SELECT h3_cell_to_vertexes('fffffffffffffff');
+----
+NULL
+
+query I
+SELECT h3_cell_to_vertex('823d6ffffffffff', 0);
+----
+2222597fffffffff
+
+query I
+SELECT h3_cell_to_vertex('823d6ffffffffff', -1);
+----
+NULL
+
+query I
+SELECT h3_vertex_to_latlng('2222597fffffffff');
+----
+[39.38084284181813, 88.57496213785487]
+
+query I
+SELECT h3_vertex_to_lat('2222597fffffffff');
+----
+39.38084284181813
+
+query I
+SELECT h3_vertex_to_lng('2222597fffffffff');
+----
+88.57496213785487