From f0a29721c9fb10f97faf386bc9d6b1b2fad97895 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 7 Apr 2019 21:50:36 +0900 Subject: Use PostgreSQL instead of MongoDB (#4572) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * wip * Update note.ts * Update timeline.ts * Update core.ts * wip * Update generate-visibility-query.ts * wip * wip * wip * wip * wip * Update global-timeline.ts * wip * wip * wip * Update vote.ts * wip * wip * Update create.ts * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * Update files.ts * wip * wip * Update CONTRIBUTING.md * wip * wip * wip * wip * wip * wip * wip * wip * Update read-notification.ts * wip * wip * wip * wip * wip * wip * wip * Update cancel.ts * wip * wip * wip * Update show.ts * wip * wip * Update gen-id.ts * Update create.ts * Update id.ts * wip * wip * wip * wip * wip * wip * wip * Docker: Update files about Docker (#4599) * Docker: Use cache if files used by `yarn install` was not updated This patch reduces the number of times to installing node_modules. For example, `yarn install` step will be skipped when only ".config/default.yml" is updated. * Docker: Migrate MongoDB to Postgresql Misskey uses Postgresql as a database instead of Mongodb since version 11. * Docker: Uncomment about data persistence This patch will save a lot of databases. * wip * wip * wip * Update activitypub.ts * wip * wip * wip * Update logs.ts * wip * Update drive-file.ts * Update register.ts * wip * wip * Update mentions.ts * wip * wip * wip * Update recommendation.ts * wip * Update index.ts * wip * Update recommendation.ts * Doc: Update docker.ja.md and docker.en.md (#1) (#4608) Update how to set up misskey. * wip * :v: * wip * Update note.ts * Update postgre.ts * wip * wip * wip * wip * Update add-file.ts * wip * wip * wip * Clean up * Update logs.ts * wip * :pizza: * wip * Ad notes * wip * Update api-visibility.ts * Update note.ts * Update add-file.ts * tests * tests * Update postgre.ts * Update utils.ts * wip * wip * Refactor * wip * Refactor * wip * wip * Update show-users.ts * Update update-instance.ts * wip * Update feed.ts * Update outbox.ts * Update outbox.ts * Update user.ts * wip * Update list.ts * Update update-hashtag.ts * wip * Update update-hashtag.ts * Refactor * Update update.ts * wip * wip * :v: * clean up * docs * Update push.ts * wip * Update api.ts * wip * :v: * Update make-pagination-query.ts * :v: * Delete hashtags.ts * Update instances.ts * Update instances.ts * Update create.ts * Update search.ts * Update reversi-game.ts * Update signup.ts * Update user.ts * id * Update example.yml * :art: * objectid * fix * reversi * reversi * Fix bug of chart engine * Add test of chart engine * Improve test * Better testing * Improve chart engine * Refactor * Add test of chart engine * Refactor * Add chart test * Fix bug * コミットし忘れ * Refactoring * :v: * Add tests * Add test * Extarct note tests * Refactor * 存在しないユーザーにメンションできなくなっていた問題を修正 * Fix bug * Update update-meta.ts * Fix bug * Update mention.vue * Fix bug * Update meta.ts * Update CONTRIBUTING.md * Fix bug * Fix bug * Fix bug * Clean up * Clean up * Update notification.ts * Clean up * Add mute tests * Add test * Refactor * Add test * Fix test * Refactor * Refactor * Add tests * Update utils.ts * Update utils.ts * Fix test * Update package.json * Update update.ts * Update manifest.ts * Fix bug * Fix bug * Add test * :art: * Update endpoint permissions * Updaye permisison * Update person.ts #4299 * データベースと同期しないように * Fix bug * Fix bug * Update reversi-game.ts * Use a feature of Node v11.7.0 to extract a public key (#4644) * wip * wip * :v: * Refactoring #1540 * test * test * test * test * test * test * test * Fix bug * Fix test * :sushi: * wip * #4471 * Add test for #4335 * Refactor * Fix test * Add tests * :clock4: * Fix bug * Add test * Add test * rename * Fix bug --- CONTRIBUTING.md | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'CONTRIBUTING.md') diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c1ad1f8041..a45ed5cb5f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -75,3 +75,61 @@ src ... Source code test ... Test code ``` + +## Notes +### placeholder +SQLをクエリビルダで組み立てる際、使用するプレースホルダは重複してはならない +例えば +``` ts +query.andWhere(new Brackets(qb => { + for (const type of ps.fileType) { + qb.orWhere(`:type = ANY(note.attachedFileTypes)`, { type: type }); + } +})); +``` +と書くと、ループ中で`type`というプレースホルダが複数回使われてしまいおかしくなる +だから次のようにする必要がある +```ts +query.andWhere(new Brackets(qb => { + for (const type of ps.fileType) { + const i = ps.fileType.indexOf(type); + qb.orWhere(`:type${i} = ANY(note.attachedFileTypes)`, { [`type${i}`]: type }); + } +})); +``` + +### `null` in SQL +SQLを発行する際、パラメータが`null`になる可能性のある場合はSQL文を出し分けなければならない +例えば +``` ts +query.where('file.folderId = :folderId', { folderId: ps.folderId }); +``` +という処理で、`ps.folderId`が`null`だと結果的に`file.folderId = null`のようなクエリが発行されてしまい、これは正しいSQLではないので期待した結果が得られない +だから次のようにする必要がある +``` ts +if (ps.folderId) { + query.where('file.folderId = :folderId', { folderId: ps.folderId }); +} else { + query.where('file.folderId IS NULL'); +} +``` + +### `[]` in SQL +SQLを発行する際、`IN`のパラメータが`[]`(空の配列)になる可能性のある場合はSQL文を出し分けなければならない +例えば +``` ts +const users = await Users.find({ + id: In(userIds) +}); +``` +という処理で、`userIds`が`[]`だと結果的に`user.id IN ()`のようなクエリが発行されてしまい、これは正しいSQLではないので期待した結果が得られない +だから次のようにする必要がある +``` ts +const users = userIds.length > 0 ? await Users.find({ + id: In(userIds) +}) : []; +``` + +### `undefined`にご用心 +MongoDBの時とは違い、findOneでレコードを取得する時に対象レコードが存在しない場合 **`undefined`** が返ってくるので注意。 +MongoDBは`null`で返してきてたので、その感覚で`if (x === null)`とか書くとバグる。代わりに`if (x == null)`と書いてください -- cgit v1.3.1-freya From b0d626d86232f80ac92e04d4535744639b0ae8fb Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 13 Apr 2019 14:04:29 +0900 Subject: Update CONTRIBUTING.md --- CONTRIBUTING.md | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'CONTRIBUTING.md') diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a45ed5cb5f..844fda5490 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -130,6 +130,10 @@ const users = userIds.length > 0 ? await Users.find({ }) : []; ``` +### 配列のインデックス in SQL +SQLでは配列のインデックスは**1始まり**。 +`[a, b, c]`の `a`にアクセスしたいなら`[0]`ではなく`[1]`と書く + ### `undefined`にご用心 MongoDBの時とは違い、findOneでレコードを取得する時に対象レコードが存在しない場合 **`undefined`** が返ってくるので注意。 MongoDBは`null`で返してきてたので、その感覚で`if (x === null)`とか書くとバグる。代わりに`if (x == null)`と書いてください -- cgit v1.3.1-freya From daf9a449e818a0335f6dab378363f3bd65595021 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 13 Apr 2019 14:31:05 +0900 Subject: Update CONTRIBUTING.md --- CONTRIBUTING.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'CONTRIBUTING.md') diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 844fda5490..3cc28bb4c8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -137,3 +137,22 @@ SQLでは配列のインデックスは**1始まり**。 ### `undefined`にご用心 MongoDBの時とは違い、findOneでレコードを取得する時に対象レコードが存在しない場合 **`undefined`** が返ってくるので注意。 MongoDBは`null`で返してきてたので、その感覚で`if (x === null)`とか書くとバグる。代わりに`if (x == null)`と書いてください + +### 簡素な`undefined`チェック +データベースからレコードを取得するときに、プログラムの流れ的に(ほぼ)絶対`undefined`にはならない場合でも、`undefined`チェックしないとTypeScriptに怒られます。 +でもいちいち複数行を費やして、発生するはずのない`undefined`をチェックするのも面倒なので、`ensure`というユーティリティ関数を用意しています。 +例えば、 +``` ts +const user = Users.findOne(userId); +// この時点で user の型は User | undefined +if (user == null) { + throw 'missing user'; +} +// この時点で user の型は User +``` +という処理を`ensure`を使うと +``` ts +const user = Users.findOne(userId).then(esure); +// この時点で user の型は User +``` +という風に書けます。 -- cgit v1.3.1-freya From 6e284c44d69837b59728fbc7821334d94fd9ae26 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 13 Apr 2019 14:34:34 +0900 Subject: Update CONTRIBUTING.md --- CONTRIBUTING.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'CONTRIBUTING.md') diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3cc28bb4c8..f284e2b591 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -143,7 +143,7 @@ MongoDBは`null`で返してきてたので、その感覚で`if (x === null)` でもいちいち複数行を費やして、発生するはずのない`undefined`をチェックするのも面倒なので、`ensure`というユーティリティ関数を用意しています。 例えば、 ``` ts -const user = Users.findOne(userId); +const user = await Users.findOne(userId); // この時点で user の型は User | undefined if (user == null) { throw 'missing user'; @@ -152,7 +152,13 @@ if (user == null) { ``` という処理を`ensure`を使うと ``` ts -const user = Users.findOne(userId).then(esure); +const user = await Users.findOne(userId).then(esure); // この時点で user の型は User ``` という風に書けます。 +もちろん`ensure`内部でエラーを握りつぶすようなことはしておらず、万が一`undefined`だった場合はPromiseがRejectされ後続の処理は実行されません。 +``` ts +const user = await Users.findOne(userId).then(esure); +// 万が一 Users.findOne の結果が undefined だったら、ensure でエラーが発生するので +// この行に到達することは無い +``` -- cgit v1.3.1-freya From 467a21f0284b475d5b09da52495c8b26e5fa80ab Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 13 Apr 2019 14:36:35 +0900 Subject: Update CONTRIBUTING.md --- CONTRIBUTING.md | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'CONTRIBUTING.md') diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f284e2b591..44501cbbc5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -161,4 +161,9 @@ const user = await Users.findOne(userId).then(esure); const user = await Users.findOne(userId).then(esure); // 万が一 Users.findOne の結果が undefined だったら、ensure でエラーが発生するので // この行に到達することは無い +// なので、.then(ensure) は +// if (user == null) { +// throw 'missing user'; +// } +// の糖衣構文のような扱いです ``` -- cgit v1.3.1-freya From 084135141fcbc4a7d17128d7dcc4a4de696deb8c Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 13 Apr 2019 14:37:45 +0900 Subject: typo --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'CONTRIBUTING.md') diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 44501cbbc5..6825225e0e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -152,13 +152,13 @@ if (user == null) { ``` という処理を`ensure`を使うと ``` ts -const user = await Users.findOne(userId).then(esure); +const user = await Users.findOne(userId).then(ensure); // この時点で user の型は User ``` という風に書けます。 もちろん`ensure`内部でエラーを握りつぶすようなことはしておらず、万が一`undefined`だった場合はPromiseがRejectされ後続の処理は実行されません。 ``` ts -const user = await Users.findOne(userId).then(esure); +const user = await Users.findOne(userId).then(ensure); // 万が一 Users.findOne の結果が undefined だったら、ensure でエラーが発生するので // この行に到達することは無い // なので、.then(ensure) は -- cgit v1.3.1-freya