Skip to content

Commit 810c5cd

Browse files
authored
Improving the use of spatial extension with wasm (#278)
* adding SimpleGeoDB to web bundle * test for flipCoordinates
1 parent 1b7a996 commit 810c5cd

File tree

10 files changed

+73
-34
lines changed

10 files changed

+73
-34
lines changed

src/bundle.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
export { default as SimpleDB } from "./class/SimpleDB.js"
2-
// Not working for now.
3-
// export { default as SimpleGeoDB } from "./class/SimpleGeoDB.js"
2+
export { default as SimpleGeoDB } from "./class/SimpleGeoDB.js"

src/class/SimpleDB.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ import replaceNullsQuery from "../methods/replaceNullsQuery.js"
6363
* const sdb = new SimpleDB()
6464
* ```
6565
*
66-
* The start() method will be called internally automatically with the first method you'll run. It initializes DuckDB and establishes a connection to the database. It sets the default_collation to NOCASE.
66+
* The start() method will be called internally automatically with the first method you'll run. It initializes DuckDB and establishes a connection to the database.
6767
*
6868
*/
6969

@@ -101,7 +101,7 @@ export default class SimpleDB {
101101
* const sdb = new SimpleDB()
102102
* ```
103103
*
104-
* The start() method will be called internally automatically with the first method you'll run. It initializes DuckDB and establishes a connection to the database. It sets the default_collation to NOCASE.
104+
* The start() method will be called internally automatically with the first method you'll run. It initializes DuckDB and establishes a connection to the database.
105105
*
106106
* @param options - An optional object with configuration options:
107107
* @param options.debug - A flag indicating whether debugging information should be logged. Defaults to false.

src/class/SimpleGeoDB.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import queryDB from "../helpers/queryDB.js"
44
import SimpleDB from "./SimpleDB.js"
55

66
/**
7-
* !!! UNDER HEAVY DEVELOPMENT !!!
8-
*
97
* SimpleGeoDB extends the SimpleDB class by adding methods for geospatial analysis. This class provides a simplified interface for working with DuckDB, a high-performance in-memory analytical database. This class is meant to be used in a web browser. For NodeJS and similar runtimes, use SimpleNodeDB with the spatial option set to true.
108
*
119
* Here's how to instantiate a SimpleGeoDB instance.
@@ -14,7 +12,7 @@ import SimpleDB from "./SimpleDB.js"
1412
* const sdb = new SimpleGeoDB()
1513
* ```
1614
*
17-
* The start() method will be called internally automatically with the first method you'll run. It initializes DuckDB and establishes a connection to the database. It sets the default_collation to NOCASE and loads the [spatial](https://duckdb.org/docs/extensions/spatial) extension.
15+
* The start() method will be called internally automatically with the first method you'll run. It initializes DuckDB and establishes a connection to the database. It loads the [spatial](https://duckdb.org/docs/extensions/spatial) extension.
1816
*
1917
*/
2018
export default class SimpleGeoDB extends SimpleDB {
@@ -66,7 +64,7 @@ export default class SimpleGeoDB extends SimpleDB {
6664
}
6765

6866
/**
69-
* Checks if a geometry is valid. (Not tested)
67+
* Checks if a geometry is valid.
7068
*
7169
* ```ts
7270
* // Checks if the geometries in column geom from table tableGeo are valid and returns a boolean in column isValid.
@@ -90,7 +88,7 @@ export default class SimpleGeoDB extends SimpleDB {
9088
}
9189

9290
/**
93-
* Flips the coordinates of a geometry. Useful for some geojson files which have lat and lon inverted. (Not tested)
91+
* Flips the coordinates of a geometry. Useful for some geojson files which have lat and lon inverted.
9492
*
9593
* ```ts
9694
* await sdb.flipCoordinates("tableGeo", "geom")

src/class/SimpleNodeDB.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import runQueryNode from "../helpers/runQueryNode.js"
2121
* const sdb = new SimpleNodeDB()
2222
* ```
2323
*
24-
* The start() method will be called internally automatically with the first method you'll run. It initializes DuckDB and establishes a connection to the database. It sets the default_collation to NOCASE and optionally loads the [spatial](https://duckdb.org/docs/extensions/spatial) extension.
24+
* The start() method will be called internally automatically with the first method you'll run. It initializes DuckDB and establishes a connection to the database. It optionally loads the [spatial](https://duckdb.org/docs/extensions/spatial) extension.
2525
*
2626
* With very expensive computations, it might create a .tmp folder, so make sure to add .tmp to your gitignore.
2727
*
@@ -35,7 +35,7 @@ export default class SimpleNodeDB extends SimpleGeoDB {
3535
* const sdb = new SimpleNodeDB()
3636
* ```
3737
*
38-
* The start() method will be called internally automatically with the first method you'll run. It initializes DuckDB and establishes a connection to the database. It sets the default_collation to NOCASE and optionally loads the [spatial](https://duckdb.org/docs/extensions/spatial) extension.
38+
* The start() method will be called internally automatically with the first method you'll run. It initializes DuckDB and establishes a connection to the database. It optionally loads the [spatial](https://duckdb.org/docs/extensions/spatial) extension.
3939
*
4040
* @param options - An optional object with configuration options:
4141
* - debug: A flag indicating whether debugging information should be logged. Defaults to false.

src/helpers/getDuckDB.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// From https://github.com/ryan-williams/next-duckdb-parquet-demo/blob/main/src/parquet.ts
2-
31
import * as duckdb from "@duckdb/duckdb-wasm"
42
import { AsyncDuckDB, DuckDBBundle } from "@duckdb/duckdb-wasm"
53
import Worker from "web-worker"

test/geodata/files/invalid.geojson

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"type": "FeatureCollection",
3+
"name": "polygon_inner_and_exterior_ring_cross",
4+
"features": [
5+
{
6+
"type": "Feature",
7+
"properties": {},
8+
"geometry": {
9+
"type": "Polygon",
10+
"coordinates": [
11+
[
12+
[13.382288, 52.515426],
13+
[13.382096, 52.514797],
14+
[13.383424, 52.51464],
15+
[13.383529, 52.515496],
16+
[13.382288, 52.515426]
17+
],
18+
[
19+
[13.382603, 52.514954],
20+
[13.38262, 52.516255],
21+
[13.383144, 52.515321],
22+
[13.383127, 52.514867],
23+
[13.382603, 52.514954]
24+
]
25+
]
26+
}
27+
}
28+
]
29+
}

test/geodata/files/point.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"type": "FeatureCollection",
3+
"features": [
4+
{
5+
"type": "Feature",
6+
"properties": {},
7+
"geometry": {
8+
"coordinates": [-73.62315106245389, 45.51412791316409],
9+
"type": "Point"
10+
}
11+
}
12+
]
13+
}

test/unit/class/SimpleGeoDB.test.ts

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,11 @@
11
import assert from "assert"
22
import SimpleGeoDB from "../../../src/class/SimpleGeoDB.js"
3-
// import { AsyncDuckDB, AsyncDuckDBConnection } from "@duckdb/duckdb-wasm"
43

54
describe("SimpleGeoDB", () => {
65
const simpleGeoDB = new SimpleGeoDB()
76
it("should instantiate a SimpleGeoDB class", () => {
87
assert.deepStrictEqual(simpleGeoDB instanceof SimpleGeoDB, true)
98
})
109

11-
it("should start and instantiate a db", async () => {
12-
console.log("NOT WORKING FOR NOW.")
13-
// await simpleGeoDB.start()
14-
// assert.deepStrictEqual(simpleGeoDB.db instanceof AsyncDuckDB, true)
15-
})
16-
it("should instantiate a connection", async () => {
17-
console.log("NOT WORKING FOR NOW.")
18-
// assert.deepStrictEqual(
19-
// simpleGeoDB.connection instanceof AsyncDuckDBConnection,
20-
// true
21-
// )
22-
})
23-
it("should close the db", async () => {
24-
console.log("NOT WORKING FOR NOW.")
25-
// await simpleGeoDB.done()
26-
})
10+
// For the rest, testing in https://observablehq.com/@nshiab/testing-simple-data-analysis-v2-0-0
2711
})
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import assert from "assert"
12
import SimpleNodeDB from "../../../src/class/SimpleNodeDB.js"
23

34
describe("flipCoordinates", () => {
@@ -6,7 +7,7 @@ describe("flipCoordinates", () => {
67
simpleNodeDB = new SimpleNodeDB({ spatial: true })
78
await simpleNodeDB.loadGeoData(
89
"geodata",
9-
"test/geodata/files/CanadianProvincesAndTerritories.json"
10+
"test/geodata/files/point.json"
1011
)
1112
})
1213
after(async function () {
@@ -15,7 +16,13 @@ describe("flipCoordinates", () => {
1516

1617
it("should flip the coordinates", async () => {
1718
await simpleNodeDB.flipCoordinates("geodata", "geom")
19+
const data = await simpleNodeDB.customQuery(
20+
`SELECT ST_AsText(geom) as geomText FROM geoData;`,
21+
{ returnDataFrom: "query" }
22+
)
1823

19-
// Not sure how to test
24+
assert.deepStrictEqual(data, [
25+
{ geomText: "POINT (45.51412791316409 -73.62315106245389)" },
26+
])
2027
})
2128
})

test/unit/methods/isValidGeo.test.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ describe("isValidGeo", () => {
1010
await simpleNodeDB.done()
1111
})
1212

13-
it("should check if geometries are valid", async () => {
13+
it("should find that geometries are valid", async () => {
1414
await simpleNodeDB.loadGeoData(
1515
"geodata",
1616
"test/geodata/files/CanadianProvincesAndTerritories.json"
@@ -23,7 +23,6 @@ describe("isValidGeo", () => {
2323
])
2424
const data = await simpleNodeDB.getData("geoData")
2525

26-
// Not very useful.
2726
assert.deepStrictEqual(data, [
2827
{
2928
nameEnglish: "Newfoundland and Labrador",
@@ -68,4 +67,16 @@ describe("isValidGeo", () => {
6867
{ nameEnglish: "Nunavut", nameFrench: "Nunavut", isValid: true },
6968
])
7069
})
70+
it("should find that geometries are not valid", async () => {
71+
// From https://github.com/chrieke/geojson-invalid-geometry
72+
await simpleNodeDB.loadGeoData(
73+
"geodata",
74+
"test/geodata/files/invalid.geojson"
75+
)
76+
await simpleNodeDB.isValidGeo("geoData", "geom", "isValid")
77+
await simpleNodeDB.selectColumns("geoData", "isValid")
78+
const data = await simpleNodeDB.getData("geoData")
79+
80+
assert.deepStrictEqual(data, [{ isValid: false }])
81+
})
7182
})

0 commit comments

Comments
 (0)