From 01e2af433b14610deab85e3e070978cc9bfb4862 Mon Sep 17 00:00:00 2001 From: Paul Kwok Date: Fri, 24 Apr 2020 16:29:00 +0800 Subject: [PATCH 1/4] [UPDATE] Update insert and update query builder to handle mssql geometry column with SRID properly --- src/query-builder/InsertQueryBuilder.ts | 4 +- src/query-builder/UpdateQueryBuilder.ts | 4 +- .../geometry-column/entity/Feature.ts | 29 +++++ .../geometry-column/geometry-column.ts | 108 ++++++++++++++++++ 4 files changed, 143 insertions(+), 2 deletions(-) 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..441370fca2 100644 --- a/src/query-builder/InsertQueryBuilder.ts +++ b/src/query-builder/InsertQueryBuilder.ts @@ -500,7 +500,9 @@ export class InsertQueryBuilder extends QueryBuilder { } else { expression += `ST_GeomFromGeoJSON(${this.connection.driver.createParameter(paramName, parametersCount)})::${column.type}`; } - } else { + } 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); } parametersCount++; diff --git a/src/query-builder/UpdateQueryBuilder.ts b/src/query-builder/UpdateQueryBuilder.ts index 49eec26d2a..f3233794f3 100644 --- a/src/query-builder/UpdateQueryBuilder.ts +++ b/src/query-builder/UpdateQueryBuilder.ts @@ -456,7 +456,9 @@ export class UpdateQueryBuilder extends QueryBuilder implements } else { expression = `ST_GeomFromGeoJSON(${this.connection.driver.createParameter(paramName, parametersCount)})::${column.type}`; } - } else { + } 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); } updateColumnAndValues.push(this.escape(column.databaseName) + " = " + expression); 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..2b92f6974e --- /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..0e1f2a7326 --- /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)"); + + }))); + +}); From 610533188dba020c7e1c8ae7f16f8f73930130fb Mon Sep 17 00:00:00 2001 From: Paul Kwok Date: Fri, 24 Apr 2020 16:44:25 +0800 Subject: [PATCH 2/4] [FIX] Fix indentation with spaces --- src/query-builder/InsertQueryBuilder.ts | 6 +- src/query-builder/UpdateQueryBuilder.ts | 6 +- .../geometry-column/entity/Feature.ts | 24 +-- .../geometry-column/geometry-column.ts | 194 +++++++++--------- 4 files changed, 115 insertions(+), 115 deletions(-) diff --git a/src/query-builder/InsertQueryBuilder.ts b/src/query-builder/InsertQueryBuilder.ts index 441370fca2..480a93ac04 100644 --- a/src/query-builder/InsertQueryBuilder.ts +++ b/src/query-builder/InsertQueryBuilder.ts @@ -500,9 +500,9 @@ 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 { + } 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); } parametersCount++; diff --git a/src/query-builder/UpdateQueryBuilder.ts b/src/query-builder/UpdateQueryBuilder.ts index f3233794f3..22ac5c5e12 100644 --- a/src/query-builder/UpdateQueryBuilder.ts +++ b/src/query-builder/UpdateQueryBuilder.ts @@ -456,9 +456,9 @@ 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 { + } 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); } updateColumnAndValues.push(this.escape(column.databaseName) + " = " + expression); diff --git a/test/core/column-kinds/geometry-column/entity/Feature.ts b/test/core/column-kinds/geometry-column/entity/Feature.ts index 2b92f6974e..9003cb5b65 100644 --- a/test/core/column-kinds/geometry-column/entity/Feature.ts +++ b/test/core/column-kinds/geometry-column/entity/Feature.ts @@ -3,27 +3,27 @@ import { Column, Entity, PrimaryGeneratedColumn } from "../../../../../src"; @Entity() export class FeatureWithoutSRID { - @PrimaryGeneratedColumn() - id: number; + @PrimaryGeneratedColumn() + id: number; - @Column() - name: string; + @Column() + name: string; - @Column({ type: 'geometry' }) - shape: string; + @Column({ type: 'geometry' }) + shape: string; } @Entity() export class FeatureWithSRID { - @PrimaryGeneratedColumn() - id: number; + @PrimaryGeneratedColumn() + id: number; - @Column() - name: string; + @Column() + name: string; - @Column({ type: 'geometry', srid: 2326 }) - shape: 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 index 0e1f2a7326..7c4017527e 100644 --- a/test/core/column-kinds/geometry-column/geometry-column.ts +++ b/test/core/column-kinds/geometry-column/geometry-column.ts @@ -2,107 +2,107 @@ import { expect } from "chai"; import "reflect-metadata"; import { Connection } from "../../../../src"; import { - closeTestingConnections, - createTestingConnections, - reloadTestingDatabases, + 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)"); - - }))); + 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)"); + + }))); }); From e7e49b3f10178c141ceadde383176a305da1aca8 Mon Sep 17 00:00:00 2001 From: Paul Kwok Date: Fri, 24 Apr 2020 16:50:08 +0800 Subject: [PATCH 3/4] [FIX] Fix semicolon, and quota characters --- test/core/column-kinds/geometry-column/entity/Feature.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/core/column-kinds/geometry-column/entity/Feature.ts b/test/core/column-kinds/geometry-column/entity/Feature.ts index 9003cb5b65..3bc959fae3 100644 --- a/test/core/column-kinds/geometry-column/entity/Feature.ts +++ b/test/core/column-kinds/geometry-column/entity/Feature.ts @@ -9,7 +9,7 @@ export class FeatureWithoutSRID { @Column() name: string; - @Column({ type: 'geometry' }) + @Column({ type: "geometry" }) shape: string; } @@ -23,7 +23,7 @@ export class FeatureWithSRID { @Column() name: string; - @Column({ type: 'geometry', srid: 2326 }) + @Column({ type: "geometry", srid: 2326 }) shape: string; } From 5abf9781a5c395196fd9c1fa4dc3105976d67a4f Mon Sep 17 00:00:00 2001 From: Paul Kwok Date: Fri, 24 Apr 2020 16:52:02 +0800 Subject: [PATCH 4/4] [FIX] Fix semicolon --- test/core/column-kinds/geometry-column/geometry-column.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/core/column-kinds/geometry-column/geometry-column.ts b/test/core/column-kinds/geometry-column/geometry-column.ts index 7c4017527e..f46fb9e016 100644 --- a/test/core/column-kinds/geometry-column/geometry-column.ts +++ b/test/core/column-kinds/geometry-column/geometry-column.ts @@ -52,7 +52,7 @@ describe("column kinds > geometry column", () => { 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)" + feature.shape = "POINT (728365.16700000037 723377.14699999988)"; await featureRepository.save(feature); // load and check if createdAt is a date (generated by db) @@ -69,7 +69,7 @@ describe("column kinds > geometry column", () => { // save a new feature const feature = new FeatureWithoutSRID(); feature.name = "feature"; - feature.shape = "POINT (0 0)" + feature.shape = "POINT (0 0)"; await featureRepository.save(feature); // load and check if createdAt is a date (generated by db) @@ -85,7 +85,7 @@ describe("column kinds > geometry column", () => { // save a new feature const feature = new FeatureWithoutSRID(); feature.name = "feature"; - feature.shape = "POINT (0 0)" + feature.shape = "POINT (0 0)"; await featureRepository.save(feature); // load and check if createdAt is a date (generated by db) @@ -94,7 +94,7 @@ describe("column kinds > geometry column", () => { expect(loadedfeature!.name).to.be.eql("feature"); expect(loadedfeature!.shape).to.be.eql("POINT (0 0)"); - feature.shape = "POINT (0.5 0.5)" + feature.shape = "POINT (0.5 0.5)"; await featureRepository.save(feature); // load and check if createdAt is a date (generated by db)