いつものようにあら便利カレンダーらしく、死んだ話です。

TypeORMというTypeScriptで使えるORMがあるんですが、
OneToManyなリレーションを作ったら死んでしまいました。

tl;dr

@ManyToOne(type => User, user => user.interests)
user: User;

このデコレータの中の引数かかないとts的なエラーを吐かずにMySQLがSyntaxError吐いて死にます。

原因

class Interest {
    @ManyToOne(type => User, user => user.interests)
    user: User;
}

これどうなっているかもぐっていくと SelectQueryBuilder.ts にたどりつきます。
createJoinExpression()というJOINされる部分のクエリを組み立てる実装がどうなっているか見てみる。

const condition = relation.inverseRelation!.joinColumns.map(joinColumn => {
    return destinationTableAlias + "." + relation.inverseRelation!.propertyPath + 
    "." + joinColumn.referencedColumn!.propertyPath + "=" +
    parentAlias + "." + joinColumn.referencedColumn!.propertyPath;
}).join(" AND ");

return " " + joinAttr.direction + " JOIN " + this.getTableName(destinationTableName) + " " + 
    this.escape(destinationTableAlias) + " ON " + this.replacePropertyNames(condition + appendedCondition);

このONのあとのJOIN条件を組み立てる部分が動きません。

SELECT ... 
FROM ... 
LEFT JOIN ... 
ON

でクエリが終わってしまってそりゃSyntaxError出るよなっていう話でした。
jsレイヤーでエラー吐けや!!!

余談

なんとこのクエリ、たまたま1480文字で死んでいたので最初はクエリがちゃんと送信できてない!みたいにしてネットワーク周りの見直しをしてました。
開発環境がdockerなのでMTUが問題になってるんじゃ!?みたいな勘違いぶちかまして情けないことに2人日くらいまるまるふっとびました。
マジなさけねえ…

ちなみに、もう一回ちゃんと調べてみようってことでTypeORMをcloneしてちゃんとデバッグした結果わかったことなので社内では誇らしい顔しながら土下座しました。

元記事はこちら

TypeORMのリレーション定義に気をつけよう。死ぬぞ。