kosappi の日記

愛知県豊橋市に住んでます。

2つの PostgreSQL 間でデータをコピーする

pg_dump ではデータベース丸ごと、テーブルごと、が指定できる。

でも、データがめちゃくちゃ大きい場合は SELECT * FROM users WHERE sex=0 みたいな SQL の結果をダンプしたくなる。 pg_dump のオプションでは、これを実現できない。

PostgreSQL ではクライアント(psql)の \copy コマンドが使える。 \copy

フロントエンド(クライアント)コピーを行います。 これはCOPY SQLコマンドを実行する操作ですが、サーバで指定ファイルに対する読み込みまたは書き込みを行うのではなく、psqlがファイルの読み書きや、サーバとローカルファイルシステム間のデータ送信を行います。 この場合、ファイルへのアクセス権限はサーバではなくローカルユーザのものを使用するので、SQLのスーパーユーザ権限は必要ありません。

PostgreSQL が持っている COPY とは厳密には違うので注意されたい。

シェルスクリプトを工夫すれば COPY でも同じことができると思うが、今回は psql でログインしてササッとやる感じ。

ダンプ

-- クライアントをデータベース1(コピー元)につなぐ
\copy (SELECT * FROM users WHERE sex=0) TO './users_sex_0.dump'

リストア

-- クライアントをデータベース2(コピー先)につなぐ
\copy users FROM './users_sex_0.dump'

PostgreSQL の WITH で再帰させる

これは弥生 Advent Calendar 2021 の7日目の記事です。

qiita.com

PosgreSQL の WITH

共通テーブル式(Common Table Expression)は一時的なテーブルを定義するもの。 サブクエリを使って SQL がネストして深くなってしまうような場合に、便利だと思う。

PostgreSQL では WITH 句で CTE を書ける。

www.postgresql.jp

こんな感じで、名前をつけた式を別の式から呼ぶことができる。便利。

WITH company_names AS (
    SELECT company_name AS name
    FROM companies
)

SELECT name
FROM company_names;

WITH で再帰できる?

WITH RECURSIVE と書けば、自分自身を参照できるようになり、再帰的に問い合わせることができる。 公式ドキュメントでも紹介されていた、1から100までの合計を計算する式は、以下のようになる。

WITH RECURSIVE t(n) AS (
    VALUES (1)
  UNION ALL
    SELECT n+1 FROM t WHERE n < 100
)
SELECT sum(n) FROM t;

-- 5050

これを ruby で書くとこんな感じだろうか。

def t(n)
  return nil if n > 100
  
  [n, *t(n + 1)]
end

pp t(1).sum

# 5050

なるほど再帰が書けるのか、と思ったけど、どうやら再帰ではないらしい。

注意: 厳密には、この手順は反復であって再帰ではありませんが、RECURSIVEはSQL標準化委員会で選ばれた用語です。

ふむ...

たしかに 再帰的問い合わせの評価 を読むとこれは for 文に近い。

とはいえ、面白いので、他にも試してみる。

添字の列を確保しておくと、ちょっと難しい数列も表現できる。

等比数列

WITH RECURSIVE t(i, n, d) AS (
    SELECT 1, 1, 3
  UNION ALL
    SELECT i + 1, n * d, d FROM t WHERE i < 10
)

SELECT i, n FROM t;
i    n
1   1
2   3
3   9
4   27
5   81
6   243
7   729
8   2187
9   6561
10  19683

フィボナッチ数列

WITH RECURSIVE fibonacci(i, x, y) AS (
    SELECT 0, 0, 1
  UNION ALL
    SELECT i + 1, y, x + y  FROM fibonacci WHERE i < 10
)

SELECT i, x FROM fibonacci;
i    x
0   0
1   1
2   1
3   2
4   3
5   5
6   8
7   13
8   21
9   34
10  55

感想

再帰じゃなくて反復なのは違和感があるし、トリッキーだと思う。なんとかならなかったのだろうか。 SQL でちょっと気の利いた計算ができるのは面白いけれど、この機能で救われる場面はあるのだろうか?と考えてしまう。

引き続き、弥生 Advent Calendar 2021 をよろしくお願いします。

qiita.com

webpack を小さく試す

学生時代から今日まで、何度も JavaScript を書く機会はあったが、いまだに良くわかっていない。 特にバンドルツールやパッケージマネージャの話が出てくると???となる。 チームの詳しい人が整備してくれた環境をなんとなく使ったりアップデートする、という状況が続いている。 まずは webpack を理解したい。 そのために、小さい構成で webpack を試してみたい。

webpack

github.com

Webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.

ブラウザで使用するために JavaScript ファイルをバンドルしてくれるツールで、いろんなリソースやアセットを変換したりバンドルしたりパッケージ化することができる。 開発中は、個別の JavaScript ファイルの間に依存関係が存在している状態が続くが、プロダクションに出す際に webpack を通すことで、1つの JavaScript ファイルにまとめてくれる。

試す

仕事で使う際はある程度育ったリポジトリで webpack を実行することが多いと思うが、今回は少ないファイル構成でやりたい。 複数の JavaScript ファイルを用意して、webpack で1つのファイルにしたい。

バンドル前

作業するディレクトリはあらかじめ git init しておく。 下記2つをバンドルしたい。

src/index.js

import messages from './messages.js';

console.log(messages);

src/messages.js

export const messages = ['first_message', 'second_message'];

webpack のインストール

まずはインストール。公式ドキュメントを見つつインストールする。

Getting Started | webpack

npm init -y
npm install webpack webpack-cli --save-dev

いろいろ置かれるので、一度 git status してみる。

On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
    node_modules/
    package-lock.json
    package.json

nothing added to commit but untracked files present (use "git add" to track)

node_modules は npm がインストールしてくれたモジュール達なので ignore する。

echo node_modules/\*\* > .gitignore

package.jsonpackage-lock.json はコミットする。

webpack の設定

We also need to adjust our package.json file in order to make sure we mark our package as private, as well as removing the main entry. This is to prevent an accidental publish of your code.

とのことなので package.json を編集する。

--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
   "name": "webpack_test",
   "version": "1.0.0",
   "description": "",
-  "main": "index.js",
+  "private": true,
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1"
   },

webpack.config.js はなくてもいい感じにやってくれるらしい。

実行結果

実行するとこういう出力になった。

$ npx webapck
npm ERR! code E404
npm ERR! 404 Not Found - GET https://registry.npmjs.org/webapck - Not found
npm ERR! 404
npm ERR! 404  'webapck@latest' is not in this registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)

npm install webpack@latest --save-dev で更新した。 もう一度実行する。

$ npx webpack
asset main.js 223 bytes [emitted] [minimized] (name: main)
orphan modules 62 bytes [orphan] 1 module
runtime modules 274 bytes 1 module
./src/index.js + 1 modules 124 bytes [built] [code generated]

WARNING in ./src/index.js 3:12-20
export 'default' (imported as 'messages') was not found in './messages.js' (possible exports: messages)

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value.
Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

webpack 5.64.2 compiled with 2 warnings in 240 ms

今回は html を置いていないため orphan なのは想定通り。 警告を順番にみていく。

WARNING in ./src/index.js 3:12-20
export 'default' (imported as 'messages') was not found in './messages.js' (possible exports: messages)

import 文が間違ってるので下記のように修正してパスした。 import 文を理解できてないことがバレた...。

import - JavaScript | MDN

-import messages from './messages.js';
+import { messages } from './messages.js';

次の警告。

The 'mode' option has not been set, webpack will fallback to 'production' for this value.
Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

mode を設定してとのこと。 今回は設定ファイルなしでやっているので、コマンドに追加のオプションを加えてみる。

$ npx webpack --mode=development

asset main.js 4.15 KiB [emitted] (name: main)
runtime modules 670 bytes 3 modules
cacheable modules 128 bytes
  ./src/index.js 66 bytes [built] [code generated]
  ./src/messages.js 62 bytes [built] [code generated]
webpack 5.64.2 compiled successfully in 78 ms

パスした。

バンドル後

dist/main.js が成果物として置かれるのだが --mode=development で書き出したため、開発用の便利ツールが含まれた大きな js になっている。 今回はバンドルの様子だけ知りたかったので --mode=production でもう一度やってみる。

$ npx webpack --mode=production

asset main.js 71 bytes [emitted] [minimized] (name: main)
orphan modules 62 bytes [orphan] 1 module
./src/index.js + 1 modules 128 bytes [built] [code generated]
webpack 5.64.2 compiled successfully in 163 ms

結果はこのようになった。

$ cat ./dist/main.js
(()=>{"use strict";console.log(["first_message","second_message"])})();%

なるほど。 依存先のソースを取り込んで、短い js に変換してくれている。

感想

最小限の構成で webpack を使ってみた。 ここからいろいろ足して、プロダクションコードで理解できていなかったアレとかコレを再現させてみたい。

最近の生活

最近の生活が安定してきたので、メモとして書いておく。

自分、妻、子1(2歳5ヶ月)、子2(9ヶ月)

だいたい5時くらいに下の子が起きるので、ミルクをあげるために自分も起きる。(起こされる) ミルクを飲み干すと寝る場合もあるが、最近は体力がついてきたようで、寝ない場合が増えてきた。 上の子が起きて朝食を食べ始めるのが7時前後なので、それまで下の子のオムツ交換や遊び相手をする。

みんな起きてきたら朝食。 食べているそばで保育園に持っていくカバンを作る。(着替えとかオムツとかを補充する) 食べ終わったら着替えさせたり体温を測ったりして、保育園に行けるようにする。

イヤイヤ期なので素直に登園してくれない場合もあるが、いろいろ小手先のテクニックで登園させる。 妻に登園を任せられる場合は、自分は7時台に仕事を始める。 フレックス勤務なので7時にはじめられれば4時にはあがることができる。

妻に登園を任せた場合も、下の子は自宅でみる。(基本的に親:子は1:1で運用) 最近は、膝にのせてパソコンを操作してる。

登園が終わったら下の子は妻にまかせて、仕事を続ける。 とはいえずっと任せるとツラいものがあるので、自分もリビングでパソコンを開くことにしている。 ミーティングや通話、ペアプログラミングなどがある場合は、作業部屋に移動する。

昼休みは1時間あるが、休むわけではなく買い出しとか家事をやる。 天気が良い日はスーパーまでの移動がけっこう気持ちいい。

昼休みが終わると午後の仕事を始める。 4時にあがる場合、ここでもう残り3時間なので、午後の仕事はスピード勝負という感じ。

4時にあがって、保育園にお迎えにいく。 天気が良い日は、近所の公園とか児童館に寄り道する。ここで遊ばせておくと、夕食もよく食べるし、夜よく寝てくれる。 スーパーに寄り道して上の子が好きな惣菜を買ったりすることもある。

妻にお迎えを任せる場合は、下の子の面倒をみつつ夕飯の支度をする。 下の子が昼寝をしている場合は夕飯が豪華になるし、起きている場合は質素になる。

夕飯がおわったら子供を風呂にいれる。 2人を別々にいれるので、けっこうしんどい。

歯磨きをして、布団を敷いて、寝かしつけ。最近は遅くても9時には寝る。 下の子は満腹の場合は揺らせば寝るので、上の子の眠たさに合わせて寝るタイミングを調整する。

寝た後は家事をしたり、仕事をしたりする。 だいたい何か仕事でやり残したことがあったりするが、ちゃんと消化しようとするとサービス残業になってしまうので、翌日のためにメモ書きをする程度。 気分がのってれば副業をやる。 やる気がないときはゲームをしてる。

感想

上の子だけのときはまだ余裕があったが、下の子が生まれて自分の育児休暇が終わってから、脳のメモリー整理が追いつかなくなってきた。 仕事をしてる最中も下の子のことを気にかけないといけないし、上の子が保育園から帰ってくる前に済ませておかないといけない事もあったりする。 こういった日常的な忙しさに加えて、引越し先を考えたり、帰省の予定を考えたり、その他イレギュラーなイベントがあったりするとパンクする。

これを解決するために、作業部屋には大学ノートを常に広げておいて、すぐにメモをとれるようにしてる。 Trello とか iCloud のメモ帳とかも試したが、ボールペンでさっと書ける便利さに勝てなかった。

早く寝るとHPが回復して、ゲームするとMPが回復する感じがする。 朝起きるのが辛かったが、晩酌をやめたら問題なかった。

GitHub のプロフィールかっこよくする

GitHub のプロフィールをかっこよくしたい

github.com/<your_id>GitHub アカウントのプロフィールが表示される。 このプロフィールをかっこよくしたい。

ここでいう「かっこよく」とは、こんな感じです。

  • どれくらい開発してるのかが可視化される
  • グラフとかチャートとか、文字以外の要素がバーンと表示される
  • なんだかかっこいい

Special Repository と README.md

Special Repository に README.md を置くと、プロフィールに内容が表示される。

私の GitHub の id は kosappi なので github.com/kosappi/kosappiREADME.md を置けば OK でした。

Special Repository を作成すると、こんな風にスペシャルな旨を教えてくれます。

github special repository info
github special repository info

Special Repository に README.md を置くと、プロフィールにこんな感じで表示されます。

github readme.md from special repository
github readme.md from special repository

この README.md を工夫すれば、なんでもできそうです。

GitHub Profile Summary Cards

README.md を充実させるものとして GitHub Profile Summary Cards があります。 これを使ってみます。 なんだかかっこいいし。

チュートリアルがあるので、そちらを参考に進めます。 github-profile-summary-cards を fork したり clone する必要はありません。

github.com

手順は大きく3つ。

  1. アクセストークンを置く
  2. GitHub Actions を追加する
  3. README.md に成果物を表示する

アクセストークンを置く

リポジトリに Personal Access Token を置きます。

Personal Access Token を作成

https://github.com/settings/tokensGenerate new token します。 必要な権限は下記の5つです。

  • repo.repo:status
  • repo.repo_deployment
  • repo.public_repo
  • user.read:user
  • user.user:email

トークンは作成した直後にしか見れないので注意してください。 紛失した場合は Regenerate token で再作成できます。

リポジトリトークンを追加する

作成したトークンを https://github.com/kosappi/kosappi/settings/secrets/actionsNew repository secret で追加します。 チュートリアルに従うと SUMMARY_CARDS_TOKEN という名前になります。

GitHub Actions を追加する

下記の workflow を追加します。

name: GitHub-Profile-Summary-Cards

on:
  schedule: # execute every 24 hours
    - cron: "* */24 * * *"
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    name: generate

    steps:
      - uses: actions/checkout@v2
      - uses: vn7n24fzkq/github-profile-summary-cards@release
        env:
          GITHUB_TOKEN: ${{ secrets.SUMMARY_CARDS_TOKEN }}
        with:
          USERNAME: ${{ github.repository_owner }}

チュートリアルのように Create new file から .github/workflows/profile-summary-cards.yml を指定して追加するのが便利だと思います。

README.md に成果物を表示する

workflow を起動して、成果物を README.md に貼り付けます。

すでに workflow は追加したので Actions タブに表示されているはずです。 Run workflow で走らせます。

workflow が終わると成果物が profile-summary-card-output というディレクトリの中に作成されます。 テーマごとにディレクトリが切られているので、好きなテーマの README.md から markdown のリンクをコピーして、root の README.md に貼り付ければ表示できます。

github profile summary cards
github profile summary cards

私はこの3つのカードを表示することにしました。テーマは github です。

感想

  • すこしかっこよくなった
  • 便利
  • github-profile-summary-cards の仕組みを知りたい
  • 自作の workflow でプロフィールを更新してみたい
  • 他にも似たような workflow は配布されてないかな?

追記

github.com

こっちの方がかっこいいですね...。