From 62d79762dbfe58219a5673ba4d404fe9f2e40436 Mon Sep 17 00:00:00 2001 From: Ceshion Date: Fri, 30 Jul 2021 20:01:31 -0400 Subject: [PATCH] fix: use nvarchar/ntext during transit for SQLServer queries (#7933) --- src/driver/sqlserver/SqlServerQueryRunner.ts | 3 -- test/github-issues/7932/entity/Example.ts | 22 ++++++++ test/github-issues/7932/issue-7932.ts | 56 ++++++++++++++++++++ 3 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 test/github-issues/7932/entity/Example.ts create mode 100644 test/github-issues/7932/issue-7932.ts diff --git a/src/driver/sqlserver/SqlServerQueryRunner.ts b/src/driver/sqlserver/SqlServerQueryRunner.ts index 1701d35a13..8ec78c6765 100644 --- a/src/driver/sqlserver/SqlServerQueryRunner.ts +++ b/src/driver/sqlserver/SqlServerQueryRunner.ts @@ -2272,15 +2272,12 @@ export class SqlServerQueryRunner extends BaseQueryRunner implements QueryRunner case "tinyint": return this.driver.mssql.TinyInt; case "char": - return this.driver.mssql.Char(...parameter.params); case "nchar": return this.driver.mssql.NChar(...parameter.params); case "text": - return this.driver.mssql.Text; case "ntext": return this.driver.mssql.Ntext; case "varchar": - return this.driver.mssql.VarChar(...parameter.params); case "nvarchar": return this.driver.mssql.NVarChar(...parameter.params); case "xml": diff --git a/test/github-issues/7932/entity/Example.ts b/test/github-issues/7932/entity/Example.ts new file mode 100644 index 0000000000..f3ca3d0818 --- /dev/null +++ b/test/github-issues/7932/entity/Example.ts @@ -0,0 +1,22 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn +} from '../../../../src'; + +@Entity() +export class Example { + + @PrimaryGeneratedColumn('uuid') + id?: string; + + @CreateDateColumn({ type: 'datetime' }) + created?: Date; + + @Column('varchar', { length: 10 }) + content: string = ''; + + @Column('char', { length: 10 }) + fixedLengthContent: string = ''; +} \ No newline at end of file diff --git a/test/github-issues/7932/issue-7932.ts b/test/github-issues/7932/issue-7932.ts new file mode 100644 index 0000000000..b2b748fdc9 --- /dev/null +++ b/test/github-issues/7932/issue-7932.ts @@ -0,0 +1,56 @@ +import "reflect-metadata"; +import { expect } from "chai"; +import { Connection } from "../../../src"; +import { closeTestingConnections, createTestingConnections, reloadTestingDatabases } from "../../utils/test-utils"; +import { Example } from "./entity/Example"; + +describe("github issues > #7932 non-ascii characters assigned to var/char columns in SQL are truncated to one byte", () => { + + let connections: Connection[]; + before(async () => { + connections = await createTestingConnections({ + enabledDrivers: ["mssql"], + entities: [Example], + schemaCreate: false, + dropSchema: true + }); + }); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("should store non-ascii characters in var/char without data loss", () => Promise.all(connections.map(async connection => { + const repo = connection.getRepository(Example); + + const entity = new Example(); + entity.content = '\u2021'; + entity.fixedLengthContent = '\u2022'; + + await repo.save(entity); + const savedEntity = + await repo.findOne({ order: { created: 'DESC' } }); + + expect(savedEntity?.content).to.be.equal(entity.content); + expect(savedEntity?.fixedLengthContent).to.be.equal('\u2022 '); + }))); + + it("should throw an error if characters in a string are too long to store", () => Promise.all(connections.map(async connection => { + const repo = connection.getRepository(Example); + + const entity = new Example(); + entity.content = '💖'; + entity.fixedLengthContent = '🏍'; + + expect(repo.save(entity)).to.eventually.be.rejectedWith(Error); + }))); + + it("should not change char or varchar column types to nchar or nvarchar", () => Promise.all(connections.map(async connection => { + const repo = connection.getRepository(Example); + + const columnMetadata = repo.metadata.ownColumns; + const contentColumnType = columnMetadata.find(m => m.propertyName === 'content')?.type; + const fixedLengthContentColumnType = columnMetadata.find(m => m.propertyName === 'fixedLengthContent')?.type; + + expect(contentColumnType).to.be.equal('varchar'); + expect(fixedLengthContentColumnType).to.be.equal('char'); + }))); +});