From 173e81b1545a6efb51f0847f8ad887362ed868ef Mon Sep 17 00:00:00 2001 From: encrypt Date: Thu, 21 Apr 2022 18:51:43 +0200 Subject: [PATCH 1/6] Fix: makeBboxCondition uses mariadb specific functions, made it works properly when postgres is used --- server/src/database/helpers.ts | 76 +++++++++++++++++++++------------- server/src/database/line.ts | 6 +-- server/src/database/marker.ts | 6 +-- server/src/database/route.ts | 6 +-- 4 files changed, 57 insertions(+), 37 deletions(-) diff --git a/server/src/database/helpers.ts b/server/src/database/helpers.ts index f75cb845..1c7dd225 100644 --- a/server/src/database/helpers.ts +++ b/server/src/database/helpers.ts @@ -113,34 +113,6 @@ export interface BboxWithExcept extends Bbox { except?: Bbox; } -export function makeBboxCondition(bbox: BboxWithExcept | null | undefined, posField = "pos"): WhereOptions { - if(!bbox) - return { }; - - const conditions = [ ]; - conditions.push( - Sequelize.fn( - "MBRContains", - Sequelize.fn("LINESTRING", Sequelize.fn("POINT", bbox.left, bbox.bottom), Sequelize.fn("POINT", bbox.right, bbox.top)), - Sequelize.col(posField) - ) - ); - - if(bbox.except) { - conditions.push({ - [Op.not]: Sequelize.fn( - "MBRContains", - Sequelize.fn("LINESTRING", Sequelize.fn("POINT", bbox.except.left, bbox.except.bottom), Sequelize.fn("POINT", bbox.except.right, bbox.except.top)), - Sequelize.col(posField) - ) - }); - } - - return { - [Op.and]: conditions - }; -} - export default class DatabaseHelpers { _db: Database; @@ -397,6 +369,54 @@ export default class DatabaseHelpers { await model.bulkCreate(this._dataToArr(data, idObj)); } + makeBboxCondition(bbox: BboxWithExcept | null | undefined, posField = "pos"): WhereOptions { + const dbType = this._db._conn.options.dialect + if(!bbox) + return { }; + + const conditions = [ ]; + if(dbType == 'postgres') { + conditions.push( + Sequelize.where( + Sequelize.fn("ST_MakeLine", Sequelize.fn("St_Point", bbox.left, bbox.bottom), Sequelize.fn("St_Point", bbox.right, bbox.top)), + "~", + Sequelize.col(posField)) + ); + } else { + conditions.push( + Sequelize.fn( + "MBRContains", + Sequelize.fn("LINESTRING", Sequelize.fn("POINT", bbox.left, bbox.bottom), Sequelize.fn("POINT", bbox.right, bbox.top)), + Sequelize.col(posField) + ) + ); + } + + if(bbox.except) { + if(dbType == 'postgres') { + conditions.push({ + [Op.not]: Sequelize.where( + Sequelize.fn("St_MakeLine", Sequelize.fn("St_Point", bbox.except.left, bbox.except.bottom), Sequelize.fn("St_Point", bbox.except.right, bbox.except.top)), + "~", + Sequelize.col(posField) + ) + }); + } else { + conditions.push({ + [Op.not]: Sequelize.fn( + "MBRContains", + Sequelize.fn("LINESTRING", Sequelize.fn("POINT", bbox.except.left, bbox.except.bottom), Sequelize.fn("POINT", bbox.except.right, bbox.except.top)), + Sequelize.col(posField) + ) + }); + } + } + + return { + [Op.and]: conditions + }; + } + renameObjectDataField(padId: PadId, typeId: ID, rename: Record }>, isLine: boolean): Promise { const objectStream = (isLine ? this._db.lines.getPadLinesByType(padId, typeId) : this._db.markers.getPadMarkersByType(padId, typeId)) as Highland.Stream; diff --git a/server/src/database/line.ts b/server/src/database/line.ts index 8dfed250..18e97cd7 100644 --- a/server/src/database/line.ts +++ b/server/src/database/line.ts @@ -1,7 +1,7 @@ import { CreationAttributes, CreationOptional, DataTypes, ForeignKey, HasManyGetAssociationsMixin, InferAttributes, InferCreationAttributes, Model, Op } from "sequelize"; import { BboxWithZoom, ID, Latitude, Line, LineCreate, ExtraInfo, LineUpdate, Longitude, PadId, Point, Route, TrackPoint } from "facilmap-types"; import Database from "./database"; -import { BboxWithExcept, createModel, dataDefinition, DataModel, getDefaultIdType, getLatType, getLonType, getPosType, getVirtualLatType, getVirtualLonType, makeBboxCondition, makeNotNullForeignKey, validateColour } from "./helpers"; +import { BboxWithExcept, createModel, dataDefinition, DataModel, getDefaultIdType, getLatType, getLonType, getPosType, getVirtualLatType, getVirtualLonType, makeNotNullForeignKey, validateColour } from "./helpers"; import { groupBy, isEqual, mapValues, omit } from "lodash"; import { wrapAsync } from "../utils/streams"; import { calculateRouteForLine } from "../routing/routing"; @@ -279,7 +279,7 @@ export default class DatabaseLines { zoom: { [Op.lte]: bboxWithZoom.zoom }, lineId: { [Op.in]: lineIds } }, - makeBboxCondition(bboxWithZoom) + this._db.helpers.makeBboxCondition(bboxWithZoom) ] }, attributes: ["pos", "lat", "lon", "ele", "zoom", "idx", "lineId"] @@ -300,4 +300,4 @@ export default class DatabaseLines { return points.map((point) => omit(point.toJSON(), ["pos"]) as TrackPoint); } -} \ No newline at end of file +} diff --git a/server/src/database/marker.ts b/server/src/database/marker.ts index c39623d2..5f7a9a24 100644 --- a/server/src/database/marker.ts +++ b/server/src/database/marker.ts @@ -1,6 +1,6 @@ import { CreationOptional, DataTypes, ForeignKey, InferAttributes, InferCreationAttributes, Model } from "sequelize"; import { BboxWithZoom, ID, Latitude, Longitude, Marker, MarkerCreate, MarkerUpdate, PadId } from "facilmap-types"; -import { BboxWithExcept, createModel, dataDefinition, DataModel, getDefaultIdType, getPosType, getVirtualLatType, getVirtualLonType, makeBboxCondition, makeNotNullForeignKey, validateColour } from "./helpers"; +import { BboxWithExcept, createModel, dataDefinition, DataModel, getDefaultIdType, getPosType, getVirtualLatType, getVirtualLonType, makeNotNullForeignKey, validateColour } from "./helpers"; import Database from "./database"; import { getElevationForPoint } from "../elevation"; import { PadModel } from "./pad"; @@ -69,7 +69,7 @@ export default class DatabaseMarkers { } getPadMarkers(padId: PadId, bbox?: BboxWithZoom & BboxWithExcept): Highland.Stream { - return this._db.helpers._getPadObjects("Marker", padId, { where: makeBboxCondition(bbox) }); + return this._db.helpers._getPadObjects("Marker", padId, { where: this._db.helpers.makeBboxCondition(bbox) }); } getPadMarkersByType(padId: PadId, typeId: ID): Highland.Stream { @@ -125,4 +125,4 @@ export default class DatabaseMarkers { return result; } -} \ No newline at end of file +} diff --git a/server/src/database/route.ts b/server/src/database/route.ts index 9618c4d3..b1714e62 100644 --- a/server/src/database/route.ts +++ b/server/src/database/route.ts @@ -2,7 +2,7 @@ import { generateRandomId } from "../utils/utils"; import { DataTypes, InferAttributes, InferCreationAttributes, Model, Op, WhereOptions } from "sequelize"; import Database from "./database"; import { BboxWithZoom, ID, Latitude, Longitude, PadId, Point, Route, RouteMode, TrackPoint } from "facilmap-types"; -import { BboxWithExcept, createModel, getPosType, getVirtualLatType, getVirtualLonType, makeBboxCondition } from "./helpers"; +import { BboxWithExcept, createModel, getPosType, getVirtualLatType, getVirtualLonType } from "./helpers"; import { calculateRouteForLine } from "../routing/routing"; import { omit } from "lodash"; import { Point as GeoJsonPoint } from "geojson"; @@ -56,7 +56,7 @@ export default class DatabaseRoutes { routeId, ...(!bboxWithZoom ? {} : { [Op.or]: [ - { [Op.and]: [ makeBboxCondition(bboxWithZoom), { zoom: { [Op.lte]: bboxWithZoom.zoom } } ] }, + { [Op.and]: [ this._db.helpers.makeBboxCondition(bboxWithZoom), { zoom: { [Op.lte]: bboxWithZoom.zoom } } ] }, ...(!getCompleteBasicRoute ? [] : [ { zoom: { [Op.lte]: 5 } } ]) @@ -210,4 +210,4 @@ export default class DatabaseRoutes { return data.map((d) => omit(d.toJSON(), ["pos"]) as TrackPoint); } -} \ No newline at end of file +} From 5408c8059b9ead4f9cc9dff74a7b5e1c87932907 Mon Sep 17 00:00:00 2001 From: encrypt Date: Thu, 21 Apr 2022 21:18:52 +0200 Subject: [PATCH 2/6] Use proper getter to retrieve dialect --- server/src/database/helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/database/helpers.ts b/server/src/database/helpers.ts index 1c7dd225..976b61cb 100644 --- a/server/src/database/helpers.ts +++ b/server/src/database/helpers.ts @@ -370,7 +370,7 @@ export default class DatabaseHelpers { } makeBboxCondition(bbox: BboxWithExcept | null | undefined, posField = "pos"): WhereOptions { - const dbType = this._db._conn.options.dialect + const dbType = this._db._conn.getDialect() if(!bbox) return { }; From cd748dda349b22f25a796ab582bad2f9a447f548 Mon Sep 17 00:00:00 2001 From: encrypt Date: Thu, 21 Apr 2022 21:45:16 +0200 Subject: [PATCH 3/6] I forgot to remove some logging --- server/src/database/helpers.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/database/helpers.ts b/server/src/database/helpers.ts index 976b61cb..7b19bdd0 100644 --- a/server/src/database/helpers.ts +++ b/server/src/database/helpers.ts @@ -252,6 +252,7 @@ export default class DatabaseHelpers { condition.include = [ ...(condition.include ? (Array.isArray(condition.include) ? condition.include : [ condition.include ]) : [ ]), this._db._conn.model(type + "Data") ]; } + const Pad = this._db.pads.PadModel.build({ id: padId } satisfies Partial> as any); const objs: Array = await (Pad as any)["get" + this._db._conn.model(type).getTableName()](condition); From d46c49d88e9a2c62d7710132380d0a4e3cf18e8a Mon Sep 17 00:00:00 2001 From: Candid Dauth Date: Wed, 15 Nov 2023 06:23:01 +0100 Subject: [PATCH 4/6] Install pg to allow using postgres --- server/package.json | 1 + yarn.lock | 137 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 137 insertions(+), 1 deletion(-) diff --git a/server/package.json b/server/package.json index 0fd16aeb..3162c719 100644 --- a/server/package.json +++ b/server/package.json @@ -92,6 +92,7 @@ "cpy-cli": "^3.1.1", "debug": "^4.3.1", "jest": "^26.6.3", + "pg": "^8.11.3", "rimraf": "^3.0.2", "ts-jest": "^26.4.4", "ts-node": "^9.1.1", diff --git a/yarn.lock b/yarn.lock index d5f6d95d..cc901387 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2901,6 +2901,13 @@ __metadata: languageName: node linkType: hard +"buffer-writer@npm:2.0.0": + version: 2.0.0 + resolution: "buffer-writer@npm:2.0.0" + checksum: 11736b48bb75106c52ca8ec9f025e7c1b3b25ce31875f469d7210eabd5c576c329e34f6b805d4a8d605ff3f0db1e16342328802c4c963e9c826b0e43a4e631c2 + languageName: node + linkType: hard + "buffers@npm:~0.1.1": version: 0.1.1 resolution: "buffers@npm:0.1.1" @@ -5146,6 +5153,7 @@ __metadata: node-cron: ^3.0.0 node-fetch: ^2.6.1 p-throttle: ^4.1.1 + pg: ^8.11.3 promisify-node: ^0.5.0 rimraf: ^3.0.2 sequelize: ^6.3.5 @@ -9208,6 +9216,13 @@ __metadata: languageName: node linkType: hard +"packet-reader@npm:1.0.0": + version: 1.0.0 + resolution: "packet-reader@npm:1.0.0" + checksum: 0b7516f0cbf3e322aad591bed29ba544220088c53943145c0d9121a6f59182ad811f7fd6785a8979a34356aca69d97653689029964c5998dc02645633d88ffd7 + languageName: node + linkType: hard + "param-case@npm:^2.1.1": version: 2.1.1 resolution: "param-case@npm:2.1.1" @@ -9401,13 +9416,89 @@ __metadata: languageName: node linkType: hard -"pg-connection-string@npm:^2.6.1": +"pg-cloudflare@npm:^1.1.1": + version: 1.1.1 + resolution: "pg-cloudflare@npm:1.1.1" + checksum: 32aac06b5dc4588bbf78801b6267781bc7e13be672009df949d08e9627ba9fdc26924916665d4de99d47f9b0495301930547488dad889d826856976c7b3f3731 + languageName: node + linkType: hard + +"pg-connection-string@npm:^2.6.1, pg-connection-string@npm:^2.6.2": version: 2.6.2 resolution: "pg-connection-string@npm:2.6.2" checksum: 22265882c3b6f2320785378d0760b051294a684989163d5a1cde4009e64e84448d7bf67d9a7b9e7f69440c3ee9e2212f9aa10dd17ad6773f6143c6020cebbcb5 languageName: node linkType: hard +"pg-int8@npm:1.0.1": + version: 1.0.1 + resolution: "pg-int8@npm:1.0.1" + checksum: a1e3a05a69005ddb73e5f324b6b4e689868a447c5fa280b44cd4d04e6916a344ac289e0b8d2695d66e8e89a7fba023affb9e0e94778770ada5df43f003d664c9 + languageName: node + linkType: hard + +"pg-pool@npm:^3.6.1": + version: 3.6.1 + resolution: "pg-pool@npm:3.6.1" + peerDependencies: + pg: ">=8.0" + checksum: 8a6513e6f74a794708c9dd16d2ccda0debadc56435ec2582de2b2e35b01315550c5dab8a0a9a2a16f4adce45523228f5739940fb7687ec7e9c300f284eb08fd1 + languageName: node + linkType: hard + +"pg-protocol@npm:^1.6.0": + version: 1.6.0 + resolution: "pg-protocol@npm:1.6.0" + checksum: e12662d2de2011e0c3a03f6a09f435beb1025acdc860f181f18a600a5495dc38a69d753bbde1ace279c8c442536af9c1a7c11e1d0fe3fad3aa1348b28d9d2683 + languageName: node + linkType: hard + +"pg-types@npm:^2.1.0": + version: 2.2.0 + resolution: "pg-types@npm:2.2.0" + dependencies: + pg-int8: 1.0.1 + postgres-array: ~2.0.0 + postgres-bytea: ~1.0.0 + postgres-date: ~1.0.4 + postgres-interval: ^1.1.0 + checksum: bf4ec3f594743442857fb3a8dfe5d2478a04c98f96a0a47365014557cbc0b4b0cee01462c79adca863b93befbf88f876299b75b72c665b5fb84a2c94fbd10316 + languageName: node + linkType: hard + +"pg@npm:^8.11.3": + version: 8.11.3 + resolution: "pg@npm:8.11.3" + dependencies: + buffer-writer: 2.0.0 + packet-reader: 1.0.0 + pg-cloudflare: ^1.1.1 + pg-connection-string: ^2.6.2 + pg-pool: ^3.6.1 + pg-protocol: ^1.6.0 + pg-types: ^2.1.0 + pgpass: 1.x + peerDependencies: + pg-native: ">=3.0.1" + dependenciesMeta: + pg-cloudflare: + optional: true + peerDependenciesMeta: + pg-native: + optional: true + checksum: 8af9468b8969fa0d73a6b349216c8cbc953d938fcae5594f2d24043060e9226a072c8085fc4230172b5576fcab4c39c8563c655f271dc2a9209b6ad5370cafe5 + languageName: node + linkType: hard + +"pgpass@npm:1.x": + version: 1.0.5 + resolution: "pgpass@npm:1.0.5" + dependencies: + split2: ^4.1.0 + checksum: 947ac096c031eebdf08d989de2e9f6f156b8133d6858c7c2c06c041e1e71dda6f5f3bad3c0ec1e96a09497bbc6ef89e762eefe703b5ef9cb2804392ec52ec400 + languageName: node + linkType: hard + "picocolors@npm:^0.2.1": version: 0.2.1 resolution: "picocolors@npm:0.2.1" @@ -9591,6 +9682,36 @@ __metadata: languageName: node linkType: hard +"postgres-array@npm:~2.0.0": + version: 2.0.0 + resolution: "postgres-array@npm:2.0.0" + checksum: 0e1e659888147c5de579d229a2d95c0d83ebdbffc2b9396d890a123557708c3b758a0a97ed305ce7f58edfa961fa9f0bbcd1ea9f08b6e5df73322e683883c464 + languageName: node + linkType: hard + +"postgres-bytea@npm:~1.0.0": + version: 1.0.0 + resolution: "postgres-bytea@npm:1.0.0" + checksum: d844ae4ca7a941b70e45cac1261a73ee8ed39d72d3d74ab1d645248185a1b7f0ac91a3c63d6159441020f4e1f7fe64689ac56536a307b31cef361e5187335090 + languageName: node + linkType: hard + +"postgres-date@npm:~1.0.4": + version: 1.0.7 + resolution: "postgres-date@npm:1.0.7" + checksum: 5745001d47e51cd767e46bcb1710649cd705d91a24d42fa661c454b6dcbb7353c066a5047983c90a626cd3bbfea9e626cc6fa84a35ec57e5bbb28b49f78e13ed + languageName: node + linkType: hard + +"postgres-interval@npm:^1.1.0": + version: 1.2.0 + resolution: "postgres-interval@npm:1.2.0" + dependencies: + xtend: ^4.0.0 + checksum: 746b71f93805ae33b03528e429dc624706d1f9b20ee81bf743263efb6a0cd79ae02a642a8a480dbc0f09547b4315ab7df6ce5ec0be77ed700bac42730f5c76b2 + languageName: node + linkType: hard + "prelude-ls@npm:^1.2.1": version: 1.2.1 resolution: "prelude-ls@npm:1.2.1" @@ -10871,6 +10992,13 @@ __metadata: languageName: node linkType: hard +"split2@npm:^4.1.0": + version: 4.2.0 + resolution: "split2@npm:4.2.0" + checksum: 05d54102546549fe4d2455900699056580cca006c0275c334611420f854da30ac999230857a85fdd9914dc2109ae50f80fda43d2a445f2aa86eccdc1dfce779d + languageName: node + linkType: hard + "split@npm:^1.0.1": version: 1.0.1 resolution: "split@npm:1.0.1" @@ -12613,6 +12741,13 @@ __metadata: languageName: node linkType: hard +"xtend@npm:^4.0.0": + version: 4.0.2 + resolution: "xtend@npm:4.0.2" + checksum: ac5dfa738b21f6e7f0dd6e65e1b3155036d68104e67e5d5d1bde74892e327d7e5636a076f625599dc394330a731861e87343ff184b0047fef1360a7ec0a5a36a + languageName: node + linkType: hard + "y18n@npm:^4.0.0": version: 4.0.3 resolution: "y18n@npm:4.0.3" From f456da2e7aa129dca4b092b970cb8dd3c9c38a8e Mon Sep 17 00:00:00 2001 From: Candid Dauth Date: Wed, 15 Nov 2023 06:27:51 +0100 Subject: [PATCH 5/6] Document how to use postgres --- docs/src/developers/server/docker.md | 37 ++++++++++++++++++++++-- docs/src/developers/server/standalone.md | 4 ++- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/docs/src/developers/server/docker.md b/docs/src/developers/server/docker.md index ae48abf0..a64a81e2 100644 --- a/docs/src/developers/server/docker.md +++ b/docs/src/developers/server/docker.md @@ -6,11 +6,11 @@ This manual assumes that you have docker set up on your system. The FacilMap server is available as [`facilmap/facilmap`](https://hub.docker.com/r/facilmap/facilmap/) on Docker Hub. The [configuration](./config.md) can be defined using environment variables. The container will expose a HTTP server on port 8080, which you should put behind a reverse proxy such as [nginx-proxy](https://hub.docker.com/r/jwilder/nginx-proxy) or [traefik](https://traefik.io/traefik/) for HTTPS support. -FacilMap needs a database supported by [Sequelize](https://sequelize.org/master/) to run, it is recommended to use MySQL/MariaDB. When creating a database for FacilMap, make sure to use the `utf8mb4` charset/collation to make sure that characters from all languages can be used on a map. By default, MySQL/MariaDB uses the `latin1` charset, which mostly supports only basic latin characters. When you start the FacilMap server for the first time, the necessary tables are created using the charset of the database. +FacilMap needs a database supported by [Sequelize](https://sequelize.org/master/) to run, it is recommended to use MySQL/MariaDB. When creating a MySQL/MariaDB database for FacilMap, make sure to use the `utf8mb4` charset/collation to make sure that characters from all languages can be used on a map. By default, MySQL/MariaDB uses the `latin1` charset, which mostly supports only basic latin characters. When you start the FacilMap server for the first time, the necessary tables are created using the charset of the database. When using PostgreSQL, the PostGIS extensions must be enabled. ## docker-compose -To run FacilMap using [docker-compose](https://docs.docker.com/compose/), here is an example `docker-compose.yml`: +To run FacilMap with MySQL using [docker-compose](https://docs.docker.com/compose/), here is an example `docker-compose.yml`: ```yaml version: "2" @@ -45,6 +45,39 @@ services: restart: unless-stopped ``` +Here is an example with Postgres: + +```yaml +version: "2" +services: + facilmap: + image: facilmap/facilmap + ports: + - 8080 + links: + - db + environment: + USER_AGENT: My FacilMap (https://facilmap.example.org/, facilmap@example.org) + DB_TYPE: postgres + DB_HOST: db + DB_NAME: facilmap + DB_USER: facilmap + DB_PASSWORD: password + ORS_TOKEN: # Get an API key on https://go.openrouteservice.org/ (needed for routing) + MAPBOX_TOKEN: # Get an API key on https://www.mapbox.com/signup/ (needed for routing) + MAPZEN_TOKEN: # Get an API key on https://mapzen.com/developers/sign_up (needed for elevation info) + MAXMIND_USER_ID: # Sign up here https://www.maxmind.com/en/geolite2/signup (needed for geoip lookup to show initial map state) + MAXMIND_LICENSE_KEY: + restart: unless-stopped + db: + image: postgis/postgis + environment: + POSTGRES_USER: facilmap + POSTGRES_PASSWORD: password + POSTGRES_DB: facilmap + restart: unless-stopped +``` + To start FacilMap, run `docker-compose up -d` in the directory of the `docker-compose.yml` file. To upgrade FacilMap, run `docker-compose pull` and then restart it by running `docker-compose up -d`. ## docker create diff --git a/docs/src/developers/server/standalone.md b/docs/src/developers/server/standalone.md index 0068eb85..f7d30205 100644 --- a/docs/src/developers/server/standalone.md +++ b/docs/src/developers/server/standalone.md @@ -2,7 +2,9 @@ The FacilMap server is written in [node.js](https://nodejs.org/en/). To run the FacilMap server, the following dependencies are needed: * You need to have a recent version of node.js and npm installed. -* You need to create a database on one of the systems supported by [Sequelize](https://sequelize.org/master/), it is recommended to use MySQL/MariaDB. When creating a database for FacilMap, make sure to use the `utf8mb4` charset/collation to make sure that characters from all languages can be used on a map. By default, MySQL/MariaDB uses the `latin1` charset, which mostly supports only basic latin characters. When you start the FacilMap server for the first time, the necessary tables are created using the charset of the database. +* You need to create a database on one of the systems supported by [Sequelize](https://sequelize.org/master/), it is recommended to use MySQL/MariaDB. + * When creating a MySQL/MariaDB database for FacilMap, make sure to use the `utf8mb4` charset/collation to make sure that characters from all languages can be used on a map. By default, MySQL/MariaDB uses the `latin1` charset, which mostly supports only basic latin characters. When you start the FacilMap server for the first time, the necessary tables are created using the charset of the database. + * When using PostgreSQL, the PostGIS extensions must be enabled. * It is recommended to run FacilMap as an unprivileged user. ## Run the latest release From 9e2d259f071b20bece1dcc0dbebceb7252473233 Mon Sep 17 00:00:00 2001 From: Candid Dauth Date: Wed, 15 Nov 2023 06:48:26 +0100 Subject: [PATCH 6/6] Round integers to avoid error on Postgres --- server/src/database/line.ts | 36 +++++++++++++++++++++++++++++++---- server/src/database/marker.ts | 9 ++++++++- server/src/database/route.ts | 9 ++++++++- 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/server/src/database/line.ts b/server/src/database/line.ts index 18e97cd7..6a1aa36e 100644 --- a/server/src/database/line.ts +++ b/server/src/database/line.ts @@ -90,9 +90,30 @@ export default class DatabaseLines { width : { type: DataTypes.INTEGER.UNSIGNED, allowNull: false, defaultValue: 4, validate: { min: 1 } }, name : { type: DataTypes.TEXT, allowNull: true, get: function(this: LineModel) { return this.getDataValue("name") || "Untitled line"; } }, distance : { type: DataTypes.FLOAT(24, 2).UNSIGNED, allowNull: true }, - time : { type: DataTypes.INTEGER.UNSIGNED, allowNull: true }, - ascent : { type: DataTypes.INTEGER.UNSIGNED, allowNull: true }, - descent : { type: DataTypes.INTEGER.UNSIGNED, allowNull: true }, + time : { + type: DataTypes.INTEGER.UNSIGNED, + allowNull: true, + set: function(this: LineModel, v: number | null) { + // Round number to avoid integer column error in Postgres + this.setDataValue("time", v != null ? Math.round(v) : v); + } + }, + ascent : { + type: DataTypes.INTEGER.UNSIGNED, + allowNull: true, + set: function(this: LineModel, v: number | null) { + // Round number to avoid integer column error in Postgres + this.setDataValue("ascent", v != null ? Math.round(v) : v); + } + }, + descent : { + type: DataTypes.INTEGER.UNSIGNED, + allowNull: true, + set: function(this: LineModel, v: number | null) { + // Round number to avoid integer column error in Postgres + this.setDataValue("descent", v != null ? Math.round(v) : v); + } + }, top: getLatType(), bottom: getLatType(), left: getLonType(), @@ -120,7 +141,14 @@ export default class DatabaseLines { pos: getPosType(), zoom: { type: DataTypes.INTEGER.UNSIGNED, allowNull: false, validate: { min: 1, max: 20 } }, idx: { type: DataTypes.INTEGER.UNSIGNED, allowNull: false }, - ele: { type: DataTypes.INTEGER, allowNull: true } + ele: { + type: DataTypes.INTEGER, + allowNull: true, + set: function(this: LinePointModel, v: number | null) { + // Round number to avoid integer column error in Postgres + this.setDataValue("ele", v != null ? Math.round(v) : v); + } + } }, { sequelize: this._db._conn, indexes: [ diff --git a/server/src/database/marker.ts b/server/src/database/marker.ts index 5f7a9a24..0fc3716f 100644 --- a/server/src/database/marker.ts +++ b/server/src/database/marker.ts @@ -43,7 +43,14 @@ export default class DatabaseMarkers { size : { type: DataTypes.INTEGER.UNSIGNED, allowNull: false, defaultValue: 25, validate: { min: 15 } }, symbol : { type: DataTypes.TEXT, allowNull: true }, shape : { type: DataTypes.TEXT, allowNull: true }, - ele: { type: DataTypes.INTEGER, allowNull: true } + ele: { + type: DataTypes.INTEGER, + allowNull: true, + set: function(this: MarkerModel, v: number | null) { + // Round number to avoid integer column error in Postgres + this.setDataValue("ele", v != null ? Math.round(v) : v); + } + } }, { sequelize: this._db._conn, // pos index is created in migration diff --git a/server/src/database/route.ts b/server/src/database/route.ts index b1714e62..300c5f63 100644 --- a/server/src/database/route.ts +++ b/server/src/database/route.ts @@ -40,7 +40,14 @@ export default class DatabaseRoutes { pos: getPosType(), zoom: { type: DataTypes.INTEGER.UNSIGNED, allowNull: false, validate: { min: 1, max: 20 } }, idx: { type: DataTypes.INTEGER.UNSIGNED, allowNull: false }, - ele: { type: DataTypes.INTEGER, allowNull: true } + ele: { + type: DataTypes.INTEGER, + allowNull: true, + set: function(this: RoutePointModel, v: number | null) { + // Round number to avoid integer column error in Postgres + this.setDataValue("ele", v != null ? Math.round(v) : v); + } + } }, { sequelize: this._db._conn, indexes: [