share facebook facebook twitter menu hatena pocket slack

2018.08.14 TUE

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

高橋 慎一

WRITTEN BY 高橋 慎一

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

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のリレーション定義に気をつけよう。死ぬぞ。

高橋 慎一

高橋 慎一

最強。敗北を知らない。

cloudpack

cloudpackは、Amazon EC2やAmazon S3をはじめとするAWSの各種プロダクトを利用する際の、導入・設計から運用保守を含んだフルマネージドのサービスを提供し、バックアップや24時間365日の監視/障害対応、技術的な問い合わせに対するサポートなどを行っております。
AWS上のインフラ構築およびAWSを活用したシステム開発など、案件のご相談はcloudpack.jpよりご連絡ください。