From 87cc6f4ecf275e48266eaf64c935b2afc5155a90 Mon Sep 17 00:00:00 2001 From: waikuen2010 Date: Sat, 16 May 2020 18:35:46 +0800 Subject: [PATCH] fix: insert and update query builder to handle mssql geometry column correctly (#5947) * [UPDATE] Update insert and update query builder to handle mssql geometry column with SRID properly * [FIX] Fix indentation with spaces * [FIX] Fix semicolon, and quota characters * [FIX] Fix semicolon Co-authored-by: Paul Kwok --- src/query-builder/InsertQueryBuilder.ts | 2 + src/query-builder/UpdateQueryBuilder.ts | 2 + .../geometry-column/entity/Feature.ts | 29 +++++ .../geometry-column/geometry-column.ts | 108 ++++++++++++++++++ 4 files changed, 141 insertions(+) create mode 100644 test/core/column-kinds/geometry-column/entity/Feature.ts create mode 100644 test/core/column-kinds/geometry-column/geometry-column.ts diff --git a/src/query-builder/InsertQueryBuilder.ts b/src/query-builder/InsertQueryBuilder.ts index 469739ad28..480a93ac04 100644 --- a/src/query-builder/InsertQueryBuilder.ts +++ b/src/query-builder/InsertQueryBuilder.ts @@ -500,6 +500,8 @@ export class InsertQueryBuilder extends QueryBuilder { } else { expression += `ST_GeomFromGeoJSON(${this.connection.driver.createParameter(paramName, parametersCount)})::${column.type}`; } + } else if (this.connection.driver instanceof SqlServerDriver && this.connection.driver.spatialTypes.indexOf(column.type) !== -1) { + expression += column.type + "::STGeomFromText(" + this.connection.driver.createParameter(paramName, parametersCount) + ", " + (column.srid || "0") + ")"; } else { expression += this.connection.driver.createParameter(paramName, parametersCount); } diff --git a/src/query-builder/UpdateQueryBuilder.ts b/src/query-builder/UpdateQueryBuilder.ts index 49eec26d2a..22ac5c5e12 100644 --- a/src/query-builder/UpdateQueryBuilder.ts +++ b/src/query-builder/UpdateQueryBuilder.ts @@ -456,6 +456,8 @@ export class UpdateQueryBuilder extends QueryBuilder implements } else { expression = `ST_GeomFromGeoJSON(${this.connection.driver.createParameter(paramName, parametersCount)})::${column.type}`; } + } else if (this.connection.driver instanceof SqlServerDriver && this.connection.driver.spatialTypes.indexOf(column.type) !== -1) { + expression = column.type + "::STGeomFromText(" + this.connection.driver.createParameter(paramName, parametersCount) + ", " + (column.srid || "0") + ")"; } else { expression = this.connection.driver.createParameter(paramName, parametersCount); } diff --git a/test/core/column-kinds/geometry-column/entity/Feature.ts b/test/core/column-kinds/geometry-column/entity/Feature.ts new file mode 100644 index 0000000000..3bc959fae3 --- /dev/null +++ b/test/core/column-kinds/geometry-column/entity/Feature.ts @@ -0,0 +1,29 @@ +import { Column, Entity, PrimaryGeneratedColumn } from "../../../../../src"; + +@Entity() +export class FeatureWithoutSRID { + + @PrimaryGeneratedColumn() + id: number; + + @Column() + name: string; + + @Column({ type: "geometry" }) + shape: string; + +} + +@Entity() +export class FeatureWithSRID { + + @PrimaryGeneratedColumn() + id: number; + + @Column() + name: string; + + @Column({ type: "geometry", srid: 2326 }) + shape: string; + +} diff --git a/test/core/column-kinds/geometry-column/geometry-column.ts b/test/core/column-kinds/geometry-column/geometry-column.ts new file mode 100644 index 0000000000..f46fb9e016 --- /dev/null +++ b/test/core/column-kinds/geometry-column/geometry-column.ts @@ -0,0 +1,108 @@ +import { expect } from "chai"; +import "reflect-metadata"; +import { Connection } from "../../../../src"; +import { + closeTestingConnections, + createTestingConnections, + reloadTestingDatabases, +} from "../../../utils/test-utils"; +import { FeatureWithoutSRID, FeatureWithSRID } from "./entity/Feature"; + +describe("column kinds > geometry column", () => { + + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"], + enabledDrivers: ["mssql"] + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + + + it("geometry column with SRID defined should be saved without error for valid WKT input", () => Promise.all(connections.map(async connection => { + const featureRepository = connection.getRepository(FeatureWithSRID); + + // save a new feature + const feature = new FeatureWithSRID(); + feature.name = "feature"; + feature.shape = "POINT (828365.16700000037 823377.14699999988)"; + await featureRepository.save(feature); + + // load and check if createdAt was a value set by us + const loadedfeature = await featureRepository.findOne(); + expect(loadedfeature).to.be.not.empty; + expect(loadedfeature!.name).to.be.eql("feature"); + expect(loadedfeature!.shape).to.be.eql("POINT (828365.16700000037 823377.14699999988)"); + + }))); + + it("geometry column with SRID defined should be updated without error for valid WKT input", () => Promise.all(connections.map(async connection => { + const featureRepository = connection.getRepository(FeatureWithSRID); + + // save a new feature + const feature = new FeatureWithSRID(); + feature.name = "feature"; + feature.shape = "POINT (828365.16700000037 823377.14699999988)"; + await featureRepository.save(feature); + + // load and check if createdAt was a value set by us + const loadedfeature = await featureRepository.findOne(); + expect(loadedfeature).to.be.not.empty; + expect(loadedfeature!.name).to.be.eql("feature"); + expect(loadedfeature!.shape).to.be.eql("POINT (828365.16700000037 823377.14699999988)"); + + feature.shape = "POINT (728365.16700000037 723377.14699999988)"; + await featureRepository.save(feature); + + // load and check if createdAt is a date (generated by db) + const updatedfeature = await featureRepository.findOne(); + expect(updatedfeature).to.be.not.empty; + expect(updatedfeature!.name).to.be.eql("feature"); + expect(updatedfeature!.shape).to.be.eql("POINT (728365.16700000037 723377.14699999988)"); + + }))); + + it("geometry column with no SRID should be saved without error for valid WKT input", () => Promise.all(connections.map(async connection => { + const featureRepository = connection.getRepository(FeatureWithoutSRID); + + // save a new feature + const feature = new FeatureWithoutSRID(); + feature.name = "feature"; + feature.shape = "POINT (0 0)"; + await featureRepository.save(feature); + + // load and check if createdAt is a date (generated by db) + const loadedfeature = await featureRepository.findOne(); + expect(loadedfeature).to.be.not.empty; + expect(loadedfeature!.name).to.be.eql("feature"); + expect(loadedfeature!.shape).to.be.eql("POINT (0 0)"); + }))); + + it("geometry column with no SRID should be updated without error for valid WKT input", () => Promise.all(connections.map(async connection => { + const featureRepository = connection.getRepository(FeatureWithoutSRID); + + // save a new feature + const feature = new FeatureWithoutSRID(); + feature.name = "feature"; + feature.shape = "POINT (0 0)"; + await featureRepository.save(feature); + + // load and check if createdAt is a date (generated by db) + const loadedfeature = await featureRepository.findOne(); + expect(loadedfeature).to.be.not.empty; + expect(loadedfeature!.name).to.be.eql("feature"); + expect(loadedfeature!.shape).to.be.eql("POINT (0 0)"); + + feature.shape = "POINT (0.5 0.5)"; + await featureRepository.save(feature); + + // load and check if createdAt is a date (generated by db) + const updatedfeature = await featureRepository.findOne(); + expect(updatedfeature).to.be.not.empty; + expect(updatedfeature!.name).to.be.eql("feature"); + expect(updatedfeature!.shape).to.be.eql("POINT (0.5 0.5)"); + + }))); + +});