Skip to content

MSSQL: lock table hint emitted outside nested join parentheses, producing invalid SQL (1.1.0 regression) #12764

Description

@rmogio-coforge

Issue description

mssql + TypeORM 1.1.0: a lock combined with a two-level relation join emits WITH (NOLOCK) outside the nested join's parentheses, so the query fails with Incorrect syntax near the keyword 'with'. 1.1.0 regression.

Expected Behavior

A query with a relation chain of depth >= 2 and setLock() should produce valid T-SQL,
with the table hint attached to each table reference.

Actual Behavior

The hint is appended after the closing ) of the nested join, where a table hint is not
allowed, and the inner table loses its hint entirely. SQL Server fails with:

QueryFailedError: Error: Incorrect syntax near the keyword 'with'. If this statement is a
common table expression, an xmlnamespaces clause or a change tracking context clause, the
previous statement must be terminated with a semicolon.

Steps to reproduce

Entities (three distinct entities, plain many-to-one — nothing special about them):

@Entity() class Country { @PrimaryColumn() id: number }

@Entity() class Profile {
  @PrimaryColumn() id: number
  @Column() countryId: number
  @ManyToOne(() => Country) @JoinColumn({ name: 'countryId' }) country: Country
}

@Entity() class User {
  @PrimaryColumn() id: number
  @Column() profileId: number
  @ManyToOne(() => Profile) @JoinColumn({ name: 'profileId' }) profile: Profile
}

Depth 1 — valid:

repo.createQueryBuilder('u').leftJoinAndSelect('u.profile', 'p').setLock('dirty_read')
FROM "user" "u" WITH (NOLOCK) LEFT JOIN "profile" "p" WITH (NOLOCK) ON "p"."id"="u"."profileId"

Depth 2 — invalid:

repo.createQueryBuilder('u')
  .leftJoinAndSelect('u.profile', 'p')
  .leftJoinAndSelect('p.country', 'c')
  .setLock('dirty_read')
FROM "user" "u" WITH (NOLOCK) LEFT JOIN ("profile" "p" LEFT JOIN "country" "c" WITH (NOLOCK) ON "c"."id"="p"."countryId") WITH (NOLOCK) ON "p"."id"="u"."profileId"
--                            ^ hint missing on "p"                                                                    ^ hint illegal here

Also reproduces through find options, so it is not query-builder specific:

repo.find({ relations: { profile: { country: true } }, lock: { mode: 'dirty_read' } })

And with the other two lock modes — pessimistic_readWITH (HOLDLOCK, ROWLOCK),
pessimistic_writeWITH (UPDLOCK, ROWLOCK) — in the same wrong position.

Depth 2 without a lock is valid, so the parenthesised nesting itself is fine; only the
hint placement is wrong.

My Environment

Dependency Version
operating system Linux
typeorm 1.1.0 (works on 1.0.0 and 0.3.29)
driver mssql

Additional Context

Regression appeared between 1.0.0 and 1.1.0: on 1.0.0 and 0.3.29 the same code emits every
join flat, with no parentheses, so the hint is always attached to a table reference.

Relevant Database Driver(s)

  • aurora-mysql
  • aurora-postgres
  • better-sqlite3
  • capacitor
  • cockroachdb
  • cordova
  • expo
  • mongodb
  • mysql
  • nativescript
  • oracle
  • postgres
  • react-native
  • sap
  • spanner
  • sqlite
  • sqljs
  • sqlserver

Are you willing to resolve this issue by submitting a Pull Request?

No, I don’t have the time and I’m okay to wait for the community / maintainers to resolve this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions