Skip to content

insert into t(cols) without a space before the paren breaks the target table and the parameter tuple #245

Description

@tiagolauer

insert into users (id, name) ... works, but the equally common insert into users(id, name) ... (no space before the paren) is parsed as if the table were named users(id,.

WordAfterKeyword<S, 'into'> takes the first space-delimited word after INTO, which is users(id,. CleanTargetIdentifier doesn't split on (, so the source table becomes users(id,. InsertColumnList then drops the same first word and looks for a ( in name) values ..., finds none, and resolves to never — which is why the parameter tuple collapses to the untyped fallback.

Repro

interface DB { users: { id: number; name: string } }

type P = Params<DB, 'insert into users(id, name) values ($1, $2)'>;
//   ^? unknown[]                       expected [number, string]

type R = StrictRow<DB, 'insert into users(id, name) values ($1, $2) returning id'>;
//   ^? QueryTypeError<'unknown table: users(id,'>      expected { id: number }

With a space (insert into users (id, name) ...) both are correct, so the failure is purely whitespace-driven and gives no hint about what to change.

Suggested fix

Split the target identifier at the first ( before CleanTargetIdentifier runs (both in SingleSource<WordAfterKeyword<S, 'into'>> and in InsertColumnList), so users(id, yields the table users and leaves (id, name) values ... for the column-list scan. The same applies to merge into t(...), and the values( spelling on the other side of the statement is already handled by ScanValuesGroups' Trim<S> extends \(${infer AfterOpen}``.

Found by the 2026-07-28 post-#243 audit on master @ 337d78a.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions