Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,9 @@ SparkSession spark = SparkSession.builder().appName("mobilityspark").master("loc
GeneratedSpatioTemporalUDFs.registerAll(spark);
```

Temporal values travel as strings in MEOS hex-WKB, and geometries as hex-EWKB, so any Spark type
system carries them:
Temporal values, spans, span sets and sets travel as their MEOS WKB bytes, a binary column, and a
column of their hex-WKB text reads as well; geometries travel as WKT or EWKT text, and boxes,
circular buffers, network points and poses as their text form:

```sql
-- accessors under their canonical MobilityDB SQL names
Expand Down Expand Up @@ -140,8 +141,8 @@ mvn -B clean test
```

`GeneratedSurfaceTest` drives the generated surface from known hex-WKB literals and asserts that
it *binds and executes*, not merely that it compiles: scalar accessors and I/O round-trips, double
/ boolean / byte marshalling, the cbuffer and npoint families, the JSON-path surface, value-array
it *binds and executes*, not merely that it compiles: scalar accessors and I/O round-trips, the
WKB bytes the functions return and the hex-WKB text they read, double / boolean / byte marshalling, the cbuffer and npoint families, the JSON-path surface, value-array
accessors, the N-by-N array UDFs, the canonical `@sqlfn` names with runtime argument-kind
dispatch, a folded out-parameter, and the H3 cell prefilter. The operator names are read from the
catalog's own `byOperator` and `positionNames` maps rather than hard-coded, so a dialect rename
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/mobilitydb/spark/MeosMemory.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
*
* Usage:
* <pre>
* Pointer tptr = GeneratedFunctions.temporal_from_hexwkb(hex);
* Pointer tptr = GeneratedFunctions.temporal_from_wkb(wkb);
* try {
* // ... use tptr ...
* } finally {
Expand Down
28 changes: 26 additions & 2 deletions src/test/java/org/mobilitydb/spark/GeneratedSurfaceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,10 @@ void portable_bare_name_dispatch_surface() {
assertEquals(Boolean.TRUE, scalar(
"SELECT " + position("&<#", "tbox") + "('" + TINT_HEX + "', '" + TINT_HEX + "')"));
// temporal comparison (#=): of a value with itself is a temporal bool, carried as
// hex-WKB, not the boolean of the traditional =
// WKB, not the boolean of the traditional =
Object teq = scalar("SELECT " + op("#=") + "('" + TINT_HEX + "', '" + TINT_HEX + "')");
assertNotNull(teq);
assertTrue(teq instanceof String, "#= answers a temporal boolean, not " + teq.getClass());
assertTrue(teq instanceof byte[], "#= answers a temporal boolean, not " + teq.getClass());
// ever comparison (?=): same value → true
assertEquals(Boolean.TRUE, scalar(
"SELECT " + op("?=") + "('" + TINT_HEX + "', '" + TINT_HEX + "')"));
Expand Down Expand Up @@ -275,6 +275,30 @@ void as_hexwkb_family_with_swallowed_size_out_param() {
"SELECT temporal_num_instants(temporal_from_hexwkb('" + hex + "'))")).intValue());
}

@Test
void values_travel_as_wkb_and_hex_wkb_stays_readable() {
String tint = "tint_in('[1@2001-01-01, 2@2001-01-02, 1@2001-01-03]')";
// A temporal, and the span a function derives from it, travel as their WKB bytes.
Object t = scalar("SELECT " + tint);
assertTrue(t instanceof byte[], "a temporal travels as WKB, got " + t.getClass());
Object span = scalar("SELECT timeSpan(" + tint + ")");
assertTrue(span instanceof byte[], "a span travels as WKB, got " + span.getClass());
// The bytes and the hex-WKB text of one value answer alike.
assertEquals(3, ((Number) scalar("SELECT numInstants(" + tint + ")")).intValue());
assertEquals(3, ((Number) scalar("SELECT numInstants('" + TINT_HEX + "')")).intValue());
// Hex-WKB in the big-endian byte order (WKB_EXTENDED | WKB_XDR = 20) is read by its
// own order, the type standing in the second and third bytes.
assertEquals(3, ((Number) scalar("SELECT numInstants(temporal_as_hexwkb("
+ tint + ", CAST(20 AS BYTE)))")).intValue());
// An aggregate over a column of hex-WKB text answers what it answers over the WKB
// of the same value.
Object overWkb = scalar("SELECT tint_out(tCount(v)) FROM (SELECT temporal_from_hexwkb('"
+ TINT_HEX + "') AS v)");
assertNotNull(overWkb);
assertEquals(overWkb,
scalar("SELECT tint_out(tCount(s)) FROM VALUES ('" + TINT_HEX + "') AS t(s)"));
}

@Test
void bool_result_value_at_timestamptz_folds_the_value_out_param() {
// tint_value_at_timestamptz(temp, t, strict, int *value) returns bool and writes
Expand Down
Loading