Deno で試すデータベースアクセス(PlanetScale編)

以前から、Deno とデータベースをつなぐ記事をいくつか書いている。
今回は、最近よく見かけるようになった PlanetScaleを、Deno でアクセスしてみる。

参考

導入

上手くいかないこと

PlanatScale を Node.js で接続する方法など親切に記載があり、参考に mysql2 を esm.sh から読むことで代替してみたが、これらは上手くいかなかった。

ベータ版機能として、JavaScript 向けサーバレスドライバーというのが有るのでそちらを使っていく。
ただし、データベースドライバーと書かれつつ Fetch 互換のドライバーであることは認識しておくべきだろう。

PlanatScale 側設定

The PlanetScale serverless driver for JavaScript に記載された方法で設定する。

設定したら、データベースの詳細 の「connect」を開く。
Connect with の選択候補に @planetscale/database が増えているので、こちらを参考にしていく。

.env に環境変数周りの設定は記載しておく。

実装

実装は以下の通り。

connect.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import "https://deno.land/std@0.153.0/dotenv/load.ts";
import { connect } from "http://esm.sh/@planetscale/database";

const config = {
host: Deno.env.get("DATABASE_HOST")!,
username: Deno.env.get("DATABASE_USERNAME")!,
password: Deno.env.get("DATABASE_PASSWORD")!,
};

const conn = connect(config);

await conn.execute(`DROP TABLE users`);

await conn.execute(`
CREATE TABLE IF NOT EXISTS users
(
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(256) NOT NULL
);
`);

await conn.execute("INSERT INTO users(name) VALUES(?)", ["桃井タロウ"]);
await conn.execute("INSERT INTO users(name) VALUES(?)", ["桃谷ジロウ"]);

const result = await conn.execute("select * from users");

console.log(result);
// => {
// headers: [ "id", "name" ],
// types: { id: "INT32", name: "VARCHAR" },
// rows: [ { id: 1, name: "桃井タロウ" }, { id: 2, name: "桃谷ジロウ" } ],
// rowsAffected: null,
// insertId: null,
// size: 2,
// statement: "select * from users",
// time: 25
// }

await conn.execute("delete FROM users WHERE name=?", ["桃井タロウ"]);

const results = await conn.transaction(async (tx) => {
const a1 = await tx.execute("INSERT INTO users(name) VALUES(?)", [
"猿原真一",
]);
const a2 = await tx.execute("INSERT INTO users(name) VALUES(?)", [
"鬼頭はるか",
]);
const a3 = await tx.execute("INSERT INTO users(name) VALUES(?)", ["犬塚翼"]);
const a4 = await tx.execute("INSERT INTO users(name) VALUES(?)", [
"雉野つよし",
]);
return [a1, a2, a3, a4];
});

console.log(results);
// => [
// {
// headers: [],
// types: {},
// rows: [],
// rowsAffected: 1,
// insertId: "3",
// size: 0,
// statement: "INSERT INTO users(name) VALUES('猿原真一')",
// time: 23
// },
// 省略
// ]

(たぶんこのクエリの実行がされた瞬間そこはきっと「さよならタロウ」時空である)

fetch API 互換のドライバーということで明確に .end() しないのは、それは確かにそうという感じ。
ちゃんとトランザクション対応してるのがすごくイイ。
select の結果もオブジェクトで返ってくるので、このまま使えるのもすごくいいだろう。


というところで、PlanetScale に Deno で接続で接続してみた。
deno.land/x - Nessie には接続先の定義として PlanetScale の定義はなさそうである。

これ出たら、喜ぶ人が一定数いるんではなかろうか。

では。