OmniAICreator/Qiita-1.07M huggingface dataset:
100日でSQLの達人になる@LeetCode! Day35 <ORDER BY句が使えない場所!?>

## 1532. The Most Recent Three Orders （問題レベル: Medium）要課金
今日の問題はこれ。
ユーザー毎に直近の注文を３つずつリストアップするという問題。
ユーザー毎なので`TOP 3`などは使えずに、`ROW_NUMBER()`を使うことはすぐに分かった。
出力結果に`ROW_NUMBER()`は不要なので、SELECT文でもう一度結果を取り出す必要がある。

アクセプトされた結果は下記。`Discuss`で高評価を得ている解答とほぼ同じだと思います。
```:SQL
SELECT t.name AS customer_name, t.customer_id, t.order_id, t.order_date
FROM
(SELECT c.name , o.customer_id, o.order_id, o.order_date, ROW_NUMBER() OVER(PARTITION BY c.customer_id ORDER BY o.order_date DESC) AS rnk
FROM orders o
JOIN customers c
ON o.customer_id=c.customer_id
) t
WHERE t.rnk <=3
ORDER BY t.name ASC, t.customer_id ASC, t.order_date DESC
```

しかし、この結果にたどり着くまでにエラーがいくつかありました。
1つ目は、最初`ORDER BY`を下記のように中に入れていた結果のエラー。
少し調べた結果、このような記載が認められていないかは不明ですが、エラーが出てしまいました。
```:SQL
SELECT t.name AS customer_name, t.customer_id, t.order_id, t.order_date
FROM
(SELECT c.name , o.customer_id, o.order_id, o.order_date, ROW_NUMBER() OVER(PARTITION BY c.customer_id ORDER BY o.order_date DESC) AS rnk
FROM orders o
JOIN customers c
ON o.customer_id=c.customer_id
ORDER BY c.name ASC, o.customer_id ASC, o.order_date DESC
) t
WHERE t.rnk <=3
```
もう一つは、最初
`ROW_NUMBER() OVER(PARTITION BY c.customer_id ORDER BY o.order_date DESC) AS rnk`の部分を
`ROW_NUMBER() OVER(PARTITION BY c.name        ORDER BY o.order_date DESC) AS rnk`としていました。
これだと、同姓同名が居るテストデータでエラーになってしまいました。

今日のポイントは`ORDER BY句の使う場所には注意!`としました。

* [LeetCode](https://leetcode.com/)の問題は、`MS SQL Server`で解いています。
深層学習、機械学習のシード固定のはまりポイント紹介

# 初めに
機械学習や深層学習をしていると学習を再現させるためにシードを固定する必要が出てくると思います。
私もその必要があり、[機械学習におけるランダムシードの研究](https://qiita.com/si1242/items/d2f9195c08826d87d6ad)を参考にしてシードを固定させていたのですが、私の環境だとどうにもうまく再現できませんでした。
同じように困っている方がいるのではないかと思い記事にしました。




# 原因
アルゴリズム内での計算による誤差が原因で特定の数値に影響を及ぼしていました。
私が使用したツール(アルゴリズム)はscikit-learnのKMeansだったのですが、predictによって得られるクラスターの予測値については全く影響ありません。
影響があったのはKMeansでパラメータ計算(fit)後のcluster_centers_の値です。
※誤差の値は非常に小さい値だったのでクラスター番号の予測には影響しなかったと思われます。






# 発見までの流れ
なぜこの問題に気付いたかの流れです。


1. シードを固定して深層学習を実施
1. シードを固定したにも関わらず学習を再現することができない
1. シードの固定漏れを調査するも見つからない
1. 予測モデルのモード(evalモード)変更忘れを疑うも問題なし
1. データの加工の流れから再現しない箇所を特定
1. 再現しない原因がKMeansのcluster_centers_の誤差ということが判明

という流れでした。
scikit-learnではシードをrandom_stateという引数で設定できるものがあり、KMeansもその引数でシードを固定していたので特定までに時間がかかってしまいました。




# 誤差検証コード
適当なデータをscikit-learnのmake_blobsで作成し誤差の検証をしてみたいと思います。


```sample.py
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
#適当なサンプルデータを作成します
X,Y = make_blobs(random_state=0, n_samples=1000, n_features=2, cluster_std=1.5, centers=4)
#K-meansのインスタンス1つ目
clf1 = KMeans(random_state=0,n_clusters=4)
clf1.fit(X)
#K-meansのインスタンス2つ目
clf2 = KMeans(random_state=0,n_clusters=4)
clf2.fit(X)
#cluster_centersの比較
print((clf1.cluster_centers_ == clf2.cluster_centers_).all())
```




おそらくFalseが出力されると思います。
Trueとなる場合もありますが複数回実行するとFalseとなります。
ただし、この誤差の影響は極めて限定されています。






# 誤差の影響について
誤差の影響を調べてみました。
上記の検証でcluster_centers_の値が一致しなかったパラメータをプロットした結果がこちらです。
![box-image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2543196/bf963eff-fada-97d8-1729-3d2b8b774245.png)

元のデータのサイズがある程度の大きさのためこの図を見る限りでは全く同じに見えます。
これだけでほぼ影響がないと言えますが一応2つのcluster_centers_の差分を計算してみます。




```sample.py
#cluster_centers_の絶対値の差分計算
np.absolute(clf1.cluster_centers_) - np.absolute(clf2.cluster_centers_)


#出力
array([[ 0.0000000e+00,  0.0000000e+00],
       [ 0.0000000e+00, -4.4408921e-16],
       [ 0.0000000e+00, -8.8817842e-16],
       [ 0.0000000e+00,  0.0000000e+00]])
```
このように非常に値が小さいことがわかります。



またこの誤差はマシンイプシロンに関係していることがわかりました。
下記のコードでマシンイプシロンを確認してみます。

```sample.py
#マシンイプシロン
np.finfo(float).eps

#出力
2.220446049250313e-16
```
上記を見ると差分がちょうどマシンイプシロンの倍数になっています。
※差分を表示する方法によっては桁が大きすぎて省略されることがあります。
おそらく非常に小さい値の計算時に誤差が発生し上記のような結果が再現しきれない問題が発生したと思われます。
こちらは四捨五入や切り捨てなどの処理を加えることで回避可能と思われます。


# 参考
[機械学習におけるランダムシードの研究](https://qiita.com/si1242/items/d2f9195c08826d87d6ad)


# まとめ
* 誤差怖い
* けど厳密な計算をしないなら誤差が発生しないようにけたを落とせば解決！
WatchKit 機能調査メモ・リンクまとめ(2022年3月 - iOS15時点)

## はじめに

Apple Watch対応アプリを作ろうと思い、調査したドキュメントへのリンクをまとめました。

Apple Watchは年々本体の性能も上がっているし、それに伴いWatch OSの機能も増え、アプリで出来ることも広がっています。一方で、アプリ作成の情報は初期のWatch OS 時代の情報が多く、最近の情報は少なめ...の印象でした。

今Apple Watchアプリを作成するなら、基本に戻ってAppleのサイトから一次情報を得るのが一番良いと思います。

## WatchKit で実現できること

WatchKitは多機能な上に似ている用語も多く、結構混乱しました。WatchKitで何が出来るのか、整理して用語を覚えておきたいところ。

[WatchKit | Apple Developer Documentation](https://developer.apple.com/documentation/watchkit)


### iOS App with Watch App
 * iOSアプリと連動して動作するWatchアプリ（Watchアプリ単体では動作しない）。典型的なWatchアプリといえば、このタイプだと思われる。

### Watch App (Independent watchOS App) 
 * iOSアプリとの連動なしで単体動作可能なWatchアプリ。2019年の watchOS 6から可能になった。Apple Watchストアからアプリをダウンロード可能。

(※余談: このタイプのアプリは数が少なく、自分も使ったことがまだないような気がする...)


### Complications
 * 文字盤の一部にテキストなど情報を表示する機能。


### Notifications
 * プッシュ通知をカスタマイズ


### Siri
 * いわゆるSiri


###  (WatchKit Extension)

* watchOS 6 以前で Watch アプリを作る際に使っていた仕組み。今は "iOS App with Watch App"に役割が代わられている？と思われる。watchOS 6 以前で動作させたいときは、この方法で作る必要がありそう。


## WatchApp 開発ドキュメント

WatchApp開発に関するドキュメントへのリンク。 iOS App with Watch App、Watch App (Independent watchOS App) について。


* [Setting Up a watchOS Project | Apple Developer Documentation](https://developer.apple.com/documentation/watchkit/creating_independent_watchos_apps/setting_up_a_watchos_project#topics)


* [Creating Independent watchOS Apps | Apple Developer Documentation](https://developer.apple.com/documentation/watchkit/creating_independent_watchos_apps)


## WatchAppからのデータ取得

* [Keeping Your watchOS Content Up to Date | Apple Developer Documentation](https://developer.apple.com/documentation/watchkit/keeping_your_watchos_content_up_to_date)

基本的には ネットワーク関連機能(Wifiなど)でデータを取得するようだ。

iOS App with Watch App で iPhone本体と通信したい場合は、[Watch Connectivity framework](https://developer.apple.com/documentation/watchconnectivity) を使う。
iOS App with Watch App では他に、BluetoothでもWatch-iOS間の通信をできるようだ。

* Data [iPhoneとApple Watch間で通信するための２つの方法【Swift】 – ゆっきぶろぐ](https://yukblog.net/iphone-watch-communication-method/)


## WatchApp での画面作成

StoryBoardを使う方式、SwiftUIを使う方式(watch OS 6 以降)、どちらも使えるようになっている。

* HIG [Getting Started - watchOS - Human Interface Guidelines - Apple Developer](https://developer.apple.com/design/human-interface-guidelines/watchos/overview/getting-started/)

* UI一覧 [WatchKitのObjectsまとめ - Qiita](https://qiita.com/am10/items/e58dfe28f024b3dc39ad)
フリーランスエンジニアになって1年になる人のメモ

## フリーランスについて
フリーランスエンジニアになって1年なので、振り返り用としてメモを残します。

## フリーランスになった経緯
  - ぶっちゃけノリでなる
    - 普通に転職活動
    - 若いうちにフリーになるのも悪くないだろうな
    - 転職活動が面倒になった

## 現実的なもの
  - 退職する前の会社から仕事をもらう
    - 今までやっていた作業を退職後も引き継ぐ形
    - 人間関係そのままでフリーになれるし、リスクも少ない(再就職もできそう)
  - サービスを使う(ランサーズ、クラウドワークス)
    - 自分でやりたい仕事を見つけて応募できる
    - やりたい時に仕事、やりたくない時は休むということができる
    - 一度請け負った会社さんに再度仕事を請け負うということもあり得る
  - フリーランスエージェントを使う
    - 自分で営業する必要がなくなる
    - 単価交渉等も代わりにしてくれる
    - 場所によっては福利厚生がついてくるところもある

## どれだけのスキルがあればやっていけるのか
 - 1年ぐらいの実務経験で問題ない
   - やはり人手不足の業界なので、実務経験があるエンジニアっていうだけで仕事はある
   - 優秀なエンジニアは企業が手放さないので、市場に出てこない
 - 期待される成果が出ないと切られることがある
   - 学習、コミュニケーションが大事
   - スキルがなくても社会人として当たり前のことはできる必要がある（敬語、マナー等）

## 大体の相場感(エージェント使っての)
 - 実務経験1年、使用言語PHP
   - 40 〜 50万ぐらい
   - 地域によっても変わる
   - プラス、トレンドな言語の経験があると単価は上がる

## フリーランスになった時の手順
 - エージェントに登録する
   - WEB上で必要事項を入力して登録する
   - 登録後スキルシートを提出する
 - エージェントさんと面談
   - スキルシートをもとに何をやってきたのか質問されたことを答えていく
   - ここで希望を言っていく(単価、勤務時間、通勤距離等)
 - エージェントさんに案件を探してもらう
   - 自分の場合はLINEで案件情報を送ってもらい、参画したいと思ったら面談したい旨を伝える
   - 業務経験1年でも結構な案件を紹介してもらえる
 - 企業の担当者と面談する
   - 就職の面接に近い
   - 面談は1回だけの場合が多い(複数の時もある)
 - 案件決定
   - エージェントに登録して、1~2週間ぐらいで案件が決まる
   - 決定後、いつ頃参画するのか決める
 - 案件に参画

 ## 参画後
 - 普通に仕事をしていく
   - 最初は環境構築、プロジェクトの仕様について把握する
   - 環境構築が落ち着いた頃合いで仕事をしていく
 - 契約更新
   - 大体3ヶ月ごとに契約が更新される
   - このタイミングで切られることもある
   - 単価アップもこのタイミング

## 転職について
実は一回転職しているので、転職についても振り返ってみる

## エンジニアさんの転職事情について
 - 1つに会社にずっといるということは最近はあまりない
   - 定年までずっといれば安泰という時代じゃなくなった
   - 新卒でずっとここにいたいと思えるような会社に出会うことは稀
 - 特にエンジニアは転職する人が多い印象
   - 転職するタイミングで年収が上がる
   - 新卒で入社した会社でしたくてもできなかったことができる
   - 人間関係に困ってた人はリセットできる

## 現実的なもの
 - 転職エージェントを使う
   - 自分に合った会社を見繕って、紹介してくれる
   - 面接、筆記試験対策をしてくれるところもある
   - 自分から会社を探す必要がない
 - 転職サイトを使う
   - 自分が入りたいと思う企業にだけ専念して転職活動ができる
   - 新卒採用時に会えなかったベンチャー企業の求人もある(Wantedlly)
   - 面談してから応募することもできる
 - 会社のホームページから応募する
   - 常に応募していることもあり、転職サイトになくても、転職したいタイミングで応募できる

## 転職した場合の給料の変化
 - 転職時に年収が上がるか下がるかは人それぞれ(自分は下がりました)
 - 上がるパターン
   - 前職より待遇が良かったり、大手企業に転職するパターン
   - 前職の経験を活かせるところに転職するパターン
 - 下がるパターン
   - 前職より待遇が悪かったり、小さい企業に転職するパターン
   - 前職とは違う職種で転職するパターン

## 転職時の手順
 - 転職サイトに登録(リクナビ、Wantedlly)
   - 就職サイトと同じように、個人情報を入力して会員登録
   - おすすめ企業などが毎週のようにメールでくる
   - 会社からスカウトメールが来ることある(自分はスカウトメールが来た企業に転職)
 - 面談する
   - 企業によっては応募前に面談してくれるところがある
   - 面談時に企業の業務内容、福利厚生を喋ってくれる
   - 実際にその企業に就職する気がなくても、話を聞くだけでもだいぶ勉強になる
 - 応募(エントリー)する
   - 転職でも就職時と同様に書類選考、面接がある
   - 面談している企業だと、面談で企業情報を知っているので、多少有利になる
   - ここでは現職は何をやってきたのか、今後は何をやってきたのか聞かれることが多い
   - 大体2回ぐらい面接がセッティングされる
 - 内定
   - 大体1週間ぐらいで内定連絡がくる
   - 自分の場合はその場で内定をくれた(ベンチャー企業でよくあることかも。。。)
   - 入社時期を決める
 - 退職願を提出する
   - 上司に退職する旨を報告する
   - 退職する1~2ヶ月前に報告することが多いと思う(就業規則に記載されてる)
   - 引き止めとかあるが、硬い意志で退職する旨を報告する
 - 退職する
 - 転職先に転職

## まとめ
新卒で入社した会社約2年→WEBベンチャー企業約1年→フリーランスエンジニア
という経歴の人のメモです。
OSにおけるデータのブロックとは

# ブロック

### ブロックとは？
ブロックとは、データの塊。
もう少し正確に言うと、バイト、ビット列の並びをひとまとめにしたもの。

### なぜブロックにするのか？
OSにおいてHDDとデータのやり取りをする際に、ブロック単位で読み書きを行う。
HDDはバイトやビットごとにデータを読み書きするとかなり性能が低下する。（実際にはできないようになっている）
そこである一定のデータの大きさ（ブロック）でデータの送受信を行うことでパフォーマンスを向上させている。

### ブロックサイズ
ブロックサイズとはブロック1つに含まれるデータ量。
基本的にはHDDが扱えるデータの最小単位の整数倍で設定される。
Apex RestRequest クラスを使ったテストコード

この質問に対する回答を考えます。よっしゃ、モックだな。あれ？エラーになる。悩みましたね。
なんだ、レスポンスじゃない。リクエストの方だけ。ああ、早とちりでした20分悩みました。


[Can someone please help me to write test class  for the Below code.](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000FTdtpSAD)

ちゃんと85％以上はカバーした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8c927a2a-6402-6130-4154-897df44d5c6b.png)

モックは要らんので、単にbody(blob型)と必要なパラメータを追加するだけですね。

```
@IsTest
public class getCaseIDNumber_test {
    
    @IsTest
    public static void testMain(){
        
        Case cs = new Case(Subject = 'Test', Origin = 'Phone', Status = 'New');
        insert cs;
        
        Attachment att = new Attachment();
        att.Name='Unit Test Attachment';
        Blob bodyBlob=Blob.valueOf('Unit Test Attachment Body');
        att.body=bodyBlob;
        att.parentId=cs.id;        
        insert att;
        
        RestRequest req = new RestRequest();
        req.requestURI = '/services/apexrest/getContactdetails';
        req.httpMethod = 'GET';
        req.addParameter('Id', att.Id);
        Test.startTest();
        
        test0002 t = new test0002();
        Boolean result = t.getCaseIDNumber(req);
        Test.stopTest();
    }


	@IsTest
    public static void testError(){
        
                
        RestRequest req = new RestRequest();
        req.requestURI = '/services/apexrest/getContactdetails';
        req.httpMethod = 'GET';
        req.addParameter('Id', null);
        Test.startTest();
        
        test0002 t = new test0002();
        Boolean result = t.getCaseIDNumber(req);
        Test.stopTest();
    }
    
    
    
}
```
【PHP】__construct(コンストラクタ)の実践的なやつ

# コード
```PHP
<?php
class Cat {
  public static $count = 0;
  public $name;
  public $age;

  public function __construct($name, $age){
    $this->name = $name;
    $this->age = $age;
    self::$count++;
  }
  public function introduce(){
    echo '名前は'.$this->name.'、' .$this->age.'歳です'.PHP_EOL;
  }
}
$cats = [];
$cats[] = new Cat('ポチ', 3);
$cats[] = new Cat('ミケ', 5);
$cats[] = new Cat('タマ', 4);
foreach($cats as $cat){
  $cat->introduce();
}
echo '動物の合計数:'.Cat::$count.'匹';
```
# 結果
```
名前はポチ、3歳です
名前はミケ、5歳です
名前はタマ、4歳です
動物の合計数:3匹

```
論文紹介【Rethinking File Mapping for Persistent Memory】（途中）

# Rethinking File Mapping for Persistent Memory

### 文献
- https://www.usenix.org/conference/fast21/presentation/neal

### 概要
Persistent MemoryはDRAMとHDD・SSDとの架け橋として注目されている。その中で、PMの高速化の研究が行われているが、IO pathの70%を占めるfile mappingは古い方法を使っている。今回は既存の2つのファイルマッピングの方法に加え、ハッシュテーブルを用いた2つで計4つのファイルマッピングの手法を評価する。

結果としてHashFSという手法は低いメモリーオーバヘッドと低い遅延でベストパフォーマンスを出した。YCSB workloadsにおいて、既存のStrataのページキャッシュextent treesを45%上回った。

### file mappingとは?
file mappingとは、デバイス上のファイルのオフセットを、メモリ上の論理オフセットに変換する構造のことである（file mapping構造）。
このfile mapping構造には3つの役割がある。
- *lookup*
- *insertions*
- *deletions*

### file mappingの課題
#### Fragmentation
フラグメンテーションはファイルシステムのオーバヘッドを大きくする一つの要因である。
端的に言うと容量不足。
正確には、全ての連続した領域にファイルを配置できない場合、もしくはファイルを拡大しようとした時に全ての隣接するブロックが他のファイルに使用されているときに起こる。
フラグメンテーションはファイルシステムが大きくなる際には避けることができない、かつ頻繁に発生する。

さらにフラグメンテーションが発生するとsequential accessesの性能が低下する。ごく当たり前だが、メモリをバラバラに配置し直すと読み込む際には強制的にランダムアクセスになるため、性能が低下する。

フラグメンテーションが発生した際には、それを解消するdefragmentationが発生するのだが、これがとても害悪。
OSにおいてこの動作はexpensive operationとされ、時間がかかる。さらに、SSDにおいてdefragmentaitonを行うと、メモリの寿命が10%も低下することがわかっている。PMにおいてもdefragmentationは好ましくない動作である。


#### lacality
ファイルを読み込む際には、OSはキャッシュを利用することでオーバヘッドを減らすことができる。localityとはつまり、ファイルがある順番に並べられていると、①のファイルにアクセスすると、隣のファイルが次にアクセスされるのを予測し、事前にファイルを読み込んでおくといった動作が可能になる。
また、file mapping構造においてもキャッシュを残しておくと、全てのデータにアクセスする際に毎回構造を辿る必要がなくなり、オーバヘッドが改善される。
さらに、効率的にキャッシュを配置すると、ランダムアクセスに対しても性能が向上するとのこと。


#### Mapping structure size
ファイルの配置を記憶するマッピング構造そのもののサイズも需要である。一般的にマッピング構造が問題になることはないが、サイズが大きくなるとファイルそのものを扱う領域が圧迫されたり、キャッシュを残す領域が減ってしまい、性能が劣化する。

既存のファイルシステムにおいてマッピング構造がelasticとされる。
つまり、マッピング構造が可変であり、ファイルのサイズや数が増えればそれに応じてマッピング構造のサイズも大きくなるというもの。しかし、メモリを効率的に扱うことができる一方、ファイルに応じてマッピング構造をリサイズするので、オーバヘッドが発生する。


#### Concurrency（同時変更）
整合性を保ったまま同時変更を可能にすることは、システムにとっては高価な機能である。

Isolationと呼ばれるファイルを孤立させる動作（同時変更するためにロックすること）は、既存のファイルマッピングの構造にとっては簡単である。ファイルのアップデートや読み取り、上書きを行う際は、readに対するロックさえすれば全ての場合に対応することができる。

問題は、writerとreaderが同時に発生した場合である。通常のファイルマッピングでは、特にextent trees(後述)では時々リサイズを行う必要がある。整合性のため、クリティカルセクション内で行われるが、これは構造が閾値を超えた場合のみ行われる。またextent treesは木構造を分割、マージを行う際に部分的な木構造のロックを行うがこれもアップデートの時のみである。

グローバルなファイルマッピング（後述）でも同時変更を念頭に入れて設計する必要がある。ファイルのグローバルアクセスにおいて、木構造の利用は好まれないが、ハッシュを扱う提案手法では、ハッシュ値が被った際にのみロックを行うので比較的簡単である。
WSL2でNetwork is unreachableになる

## はじめに
サブPCのWindowsで、WSL2のUbuntuにTerraformをインストールしようと試みていました。

https://learn.hashicorp.com/tutorials/terraform/install-cli
ここのLinux版の手順の通り進めていたところ、
```
$ sudo apt-get update
Err:1 http://ppa.launchpad.net/ansible/ansible/ubuntu focal InRelease
  Cannot initiate the connection to ppa.launchpad.net:80 (2001:67c:1560:8008::19). - connect (101: Network is unreachable) Could not connect to ppa.launchpad.net:80 (91.189.95.85), connection timed out
```
このようにapt-get updateでNetwork is unreachableというエラーが出てしまいました。



## どこが問題だったか

結論から言うと私の場合**ファイアウォールでした。**
あるあるですね。

いつだって不可解な動きの裏にはファイアウォールがいます。

きっと接続先からこちらへの通信をファイアウォールが遮断することでコネクションが確立できず、結果Network is unreachableということになってしまうのでしょう。

## Symantec Endpoint Protectionの場合の設定変更
私のPCにはSymantec Endpoint Protectionが入っていたので、こいつの設定を変更しました。

1. まずはSymantec Endpoint Protectionを開きます。
![capture53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523625/0d8b7458-f29e-ada9-315b-248996471b6b.png)

1. **ネットワークとホストのエクスプロイト緩和機能**のオプションから、設定の変更を選びましょう。

1. ファイアウォールタブを選び、「不一致IPトラフィックの設定」という項目を確認してみましょう。
ここが画像のように「アプリケーショントラフィックのみを許可する」になっていたら変更が必要です。

![capture54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523625/bf98498e-abaf-bc77-af83-2b216999ad1e.png)

1. 「IPトラフィックを許可する」にチェックを入れて「OK」すれば完了です。


他のファイアウォールでもきっと同じような設定項目があるはずなので、
適宜調べて変更してみてください。


## 他の解決策について
「WSL Network is unreachable」
などで調べると現在真っ先に出てくるのが以下のstackoverflowです。

https://stackoverflow.com/questions/66338549/wsl2-network-unreachable

ここで書かれている解決策はざっくりいうと、
- wsl --shutdownでwslを再起動しろ
- Ubuntu側の/etc/resolv.confなど諸々を修正しろ

といったことでした。

それらで解決したという人もいるみたいなので、ファイアウォールの設定を変更しても解決しない場合はこちらを試してみる価値はあるかと思います。
Homebrew swiftlint command not found in Xcode

# Homebrew経由でインストールしたswiftlintがXcodeから見えない問題

# 現象
ターミナルからはswiftlintが実行できるのに、XcodeのRun Scriptからは `swiftlint: command not found` になっちゃう。

# 解決方法
スクリプト内でApple Silicon向けのbrew directoryをPATH指定する

```sh
# Adds support for Apple Silicon brew directory
export PATH="$PATH:/opt/homebrew/bin"

if which swiftlint; then
    swiftlint autocorrect && swiftlint
else
  echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi
```

# 環境
Xcode 13.2.1

# 参考
https://stackoverflow.com/questions/65991508/swiftlint-cant-be-found-on-apple-silicon-xcode%EF%BC%89
[MySQL]任意の順番で連番を割り振る

並び替えるためのデータを個別に持たせたとき、任意の順番で連番を振るのに少し悩んだ。
あまり効率的ではない部分があるかも（逆順で書かせてるところとか）。

# SQL文

```sql
SET
@cnt_i:=0;

UPDATE
sample
SET
pos = (@cnt_i := @cnt_i + 1)
ORDER BY
FIELD(id, ...) DESC
,id;
```

# 解説

```sql
ORDER BY
FIELD(id, ...) DESC
```

FIELD()の第一引数に並び順を指定するカラムを指定し、
第二引数以降に、任意の順番を逆順で指定する。

```sql
FIELD(id,8,6,2) DESC
```

例えばidを2,6,8の順番で並び替えたい場合は、このように指定する。

```sql
ORDER BY
-- FIELD(id, ...) DESC
,id;
```

idが指定されていないカラムについては、idの昇順で並び替える。

# 例

|id|pos|
|-|-|
|1|1|
|2|2|
|3|3|
|4|4|
|5|5|
|6|6|
|7|7|
|8|8|
|9|9|

このようなsampleテーブルがあるとする。
posは並び順データを格納するカラム。

このsampleテーブルに対して以下のSQLを実行すると…

```sql
SET
@cnt_i:=0;

UPDATE
sample
SET
pos = (@cnt_i := @cnt_i + 1)
ORDER BY
FIELD(id,8,6,2) DESC
,id;
```

|id|pos|
|-|-|
|2|1|
|6|2|
|8|3|
|1|4|
|3|5|
|4|6|
|5|7|
|7|8|
|9|9|

このように並び順が格納される。
2→6→8と任意の順番で連番が割り振られる。
順番を指定していないカラムは、id昇順を基準として続く連番が割り振られる。
XAMPPのMySQL、phpMyAdminですべてのユーザーを削除してしまったら

# 結論
`xampp/mysql/backup`に`xampp/mysql/data`のバックアップが入っているので置き換えます。

# おわりに
phpMyAdminを開いて早々にユーザーをすべて削除するという愚行をしてしまって焦りましたが、何とか復活できたのでよかったです。
個人アプリをリリースして1週間が経って思ったこと

## 何を作ったのか？
プログラミングソースコード売買プラットフォーム
https://softpick.net
![root.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1195442/62e16947-4f66-6c69-97a1-298943bcd758.jpeg)

## なぜ作ったのか？
僕はこのサービスを作るときもそうですが、ハッカソンなどでもわからないことはqiitaに書いてある内容をそのままコピペしたり、ドキュメントのサンプルをそのままコピペしたりして実装をしていました。僕が駆け出しの頃は検索能力も著しく低かったので、フレームワークやライブラリの強みを全く活かしきれずにいました。
優秀なエンジニアが書いたライブラリの選定から正しい拡張の仕方などがみれるソースコードプラットフォームがあったらなと思い作りました。

### 率直な感想
楽しい。自分が作ったサービスが人に見てもらって使ってもらって、指摘・感想がいただけることがすごく嬉しかったです。実際オフラインで知り合いに見てもらうより、アナリティクスで見る方がユーザーの正直な感想がわかりました。サービスが自分に必要がないとわかれば無意識にサイトを閉じ流ので、どのページでそう思ったのかを知ることができました。

連続でボタンを押してしまったり、フォームで入力して欲しいことがうまく伝わっていなかったりして自分が思っているようにユーザーが動いてくれないことが多く（UI,UXが悪いせいで）、その結果予期しないバグが起こりました。順次対応しています。


### AWSの請求が怖い
2月中旬ぐらいからAWSを使用していますが、2月の請求額が消費税こみで2,476円でした。
Fargateのコンテナは一番スペックの低いものを採用していますがこれが一番高かったです。インフラが苦手すぎて試しながら構築したので、無駄なところにちょこちょこ課金されているかもしれません。設計ミスで何十万とかの請求がきそうで、100円毎にアラートをかけて毎日ビクビクしながら過ごしていました。
![スクリーンショット 2022-03-07 14.08.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1195442/07d2ba74-5309-b2e8-30de-b16c9b1eef72.png)



### やってよかったこと

#### エラーモニタリング
エラーモニタリングツールにrollbarを採用しました。無料かつslackに通知を送りたく、rollbarはそれが可能だったからです。
エラーモニタリングを使用することで、↓こんな感じでslackに通知することができるので、本番環境で起こったエラーが検知できるようになります。
![スクリーンショット 2022-03-07 3.17.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1195442/6c8d3df8-77f2-862e-044e-377c863c19e7.png)
rollbarではエラーした時刻、エラーした行数、ユーザのOS、ユーザーのIPアドレスなどが確認できます。

#### Google analytics
google analyticsはアクセス解析ツールです。サイトに訪れたユーザー数、流入経路、サイト滞在時間、ユーザー属性などさまざまなことがわかります。

サービスを運営する上で、どういうユーザーがどこから飛んできたのかを知ることはとても重要です。
[コロナで大学を1年休学して、ソースコード売買プラットフォームを作りました](https://qiita.com/kenshin_kenboo/items/a3caa99dc7989ac470bc "コロナで大学を1年休学して、ソースコード売買プラットフォームを作りました") を書いたのが28日です。
![スクリーンショット 2022-03-07 3.34.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1195442/4774eecf-3e64-167f-d164-025200c64342.png)

![スクリーンショット 2022-03-07 3.36.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1195442/03cfe6fc-29e3-8b69-318e-964ee2266326.png)
その結果、初日に370ユーザーに訪問していただき、約9割がqiitaからの訪問でした。しかし、勢いは初日だけで2日目以降はどんどん下がっていく一方でした。なので、qiitaで記事をどんどん書いていってユーザーを増やしていこうという狙いで今執筆しているという訳です笑
ユーザーの推移は今後も別の記事であげていこうと思っています。


## 今後の展望
サイトに訪問したユーザーのうちほとんどがソースコードをアップせずに離脱してしまうことが分かったので、アップしたソースコードを解析していいコードかどうかを点数で出したり、バッジやランキングを導入したりしてコードアップを促していこうと思いました。
それと利用規約に対してのフィードバックも得られたので、そちらも対応していこうと思っています。
NextJs フロントサイド .env 値の取得方法

## NextJs フロントサイド .env 値の取得方法

[こちらの記事](https://qiita.com/ktanoooo/items/64cad61096cf45f18c24)に書いてある通り
NextJs ver9.4以上であれば
```js:.env
NEXT_PUBLIC_TEST=next_public_test
```
のように先頭にNEXT_PUBLICを付けることで
フロントサイドにて
**process.env.NEXT_PUBLIC_TEST**
で値を取得可能。

開発環境ごとの.envを扱いたい場合は
[こちらの記事](https://qiita.com/ktanoooo/items/64cad61096cf45f18c24)を参考にしましょう！
Visual Studioビルドヒープ不足エラー C1060

# C1060エラー
ビルド時に、ヒープの領域が足りなくなること。
実際私の場合、300MBぐらいのCファイルをビルド際に上記のエラーが発生しまし。
# 解決方法
64Bitのコンパイルを使用すれば、エラーが解決できます。
Visual Studioで64bitコンパイラツールセットを使う⽅法は以下です。
1. プロジェクトの`.vcxproj`ファイルを開く
2. `<PropertyGroup Label="Globals">`の中に`<PreferredToolArchitecture>x64</PreferredToolArchitecture>`を追加

    <PropertyGroup Label="Globals">
        ...
        <PreferredToolArchitecture>x64</PreferredToolArchitecture>
    </PropertyGroup>

`<PropertyGroup Label="Globals">`
はプロジェクトのプロパティにおけるすべての構成で、Release、Debugなどの構成やプラットフォームごとに切り替えたい場合は、"Globals"ではなく各構成ごとのブロックに書き加えればいい。
# 注意
VS2013 Expressは、上記の解決方法が適用されません。64Bitコンパイラツールが入っていません。
# 参考
https://kenkyu-note.hatenablog.com/entry/2019/11/01/193301
Docker Commad

# image ls 
イメージの一覧を出力します

オプション
- docker image ls -a : 全イメージを表示します。
- docker image ls -q : イメージ ID のみを表示します。

## search
Docker Hub 上のイメージを検索します。
`docker search [オプション] TERM`
オプション

- `--limit [number]`:出力結果の最大数　例`docker search --limit 3 tomcat`

## pull
レジストリからイメージまたはリポジトリを取得します。
`docker pull [オプション] NAME[:TAG|@DIGEST]`

# rmi
イメージ削除コマンドです。1つまたは複数のイメージを削除します。
` docker rmi [オプション] IMAGE [IMAGE...]`

# run
新たなコンテナー内でコマンドを実行します。
`docker run [オプション] IMAGE [COMMAND] [ARG...]`
例：`docker run --name test -it debian`
オプション

- `-i`:アタッチされていなくても STDIN は開放し続けます。`-t`と一緒に使用
- `-t`:擬似 TTY を割り当てます。`-i`と一緒に使用
- `--name`:コンテナーに名前を割り当てます。
- `-d`:デタッチ起動（バックグラウンド）
- `p` : ポート設定　`-p ホストポート コンテナ（ゲスト）ポート コンテナ名`　例`docker run -it -p 8080:8080 tomcat`



# ps
コンテナーの一覧表示。（デフォルトは実行中コンテナーのみ。）
オプション
- `-a`:コンテナーすべてを表示します

# start
停止しているコンテナーを起動する。
`docker start [オプション] CONTAINER [CONTAINER...]`
例：`docker start my_container`

# stop
終了
# docker kill
強制終了
# docker rm
1 つまたは複数のコンテナーを削除します。
`docker rm [オプション] CONTAINER [CONTAINER...]`
例：`docker rm /redis`

# container
コンテナーを管理します。
`docker container COMMAND`

# logs
コンテナーからログを取得します。
`docker logs [オプション] CONTAINER`
オプション
- `-f, --follow=false` : ログの出力をフォロー（表示し続ける）
- `tail` : ログの最後から指定した行数を表示 例`docker logs -f -t --since="2018-02-08" --tail=100 CONTAINER_ID`

# top
コンテナー内での実行プロセスを表示します。
`docker top CONTAINER [ps オプション]`

# inspect
Docker オブジェクトに対する低レベル情報を返します。

# attach
ローカルの標準入出力やエラー出力を実行中コンテナーにアタッチします。
起動中のコンテナーに入ります。
`docker attach [オプション] CONTAINER`
例：`docker attach topdemo`

# exec
ホスト側で実行中のコンテナー内でコマンドを実行します。
`docker exec [オプション] CONTAINER COMMAND [ARG...]`
例：`docker exec -d ubuntu_bash touch /tmp/execWorks`
バックグラウンドで実行中のコンテナーubuntu_bash内において、新規ファイル/tmp/execWorksを生成します。

オプション
- `i`:アタッチしていなくても STDIN をオープンにし続ける
- `t`:疑似ターミナル (pseudo-TTY) の割り当て

よく使用するコマンド
コンテナ入り：`docker exec -it [containerid] bash`

# cp
ファイルやフォルダーを、コンテナー間あるいはローカルファイルシステムとの間でコピーします。
`docker cp [オプション] CONTAINER:SRC_PATH DEST_PATH|-`

# build
Dockerfile からイメージをビルドします。
`docker build [オプション] PATH | URL | -`

# Ctrl+P+Q/exit
- Ctrl+P+Q:終了
- exit:停止・終了
【PHP】staticはなぜ使うのか？※__constructと組み合わせることで最大の効果を発揮する

static単体では【インスタンスを省略】だけだが、__constructと組み合わせることで
各インスタンスメリットの共通データや、各インスタンスメソットで使わない処理を書くことができる
それがstaticメソット


```PHP 
<?php
class Animal
{
    private static $animals = [];
    function __construct($name, $food) {
        $this->name = $name;
        $this->food = $food;
        array_push(self::$animals, '【'.$name.'】');
    }
    static function list() {
        echo join("と", self::$animals)."の食べ物を紹介します" . PHP_EOL;
    }
    function eat() {
        echo $this->name . "は" . $this->food . "を食べます" . PHP_EOL;
    }
}

$data = [
    ['name' => '猫','feed' => 'キャットフード'],
    ['name' => '犬','feed' => 'ドッグフード'],
    ['name' => '鳥','feed' => 'パフ・ザ・フルーツ'],
];
foreach ($data as $list) $animal[] = new Animal($list['name'],$list['feed']);
Animal::list();
foreach ($animal as $list) $list->eat();
```
# 結果
```
【猫】と【犬】と【鳥】の食べ物を紹介します
猫はキャットフードを食べます
犬はドッグフードを食べます
鳥はパフ・ザ・フルーツを食べます
```
ネストされた（重ねられた）スプライト：アンカーとパーツ「こども向けのSnap!かいせつ」

たくさんのスプライトをいちどに動かすことができるような「超スプライト」のようなものがあるとべんりです。たとえば、人間の体をあらわすには、あたまやくびやむねや手や足といったものがありますよね。それぞれをべつべつに動かすこともできますが、右足が前に、左足が後ろにといったことをこまかく書かなくても、体全体を動かせるとべんりです。Snap!では、AというスプライトがB,C,Dといった他のスプライトをそのパーツ（一部分）とできるように、Aというスプライトがふくすうのスプライトのアンカー（いかり）となることができます。これをネストされた（重ねられた）スプライトといいます。ネストされたスプライトを作るためには、スプライトエリアのスプライトのアイコンをステージ上のアンカーとしたいスプライトの上にドラッグして重ねることでできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671164/62ad6155-b10d-63b8-7e3c-b703aec0c335.png)
ネストされたスプライトは、下のようにアンカーのスプライトにはパーツのスプライトが小さく書かれ、パーツのスプライトにははいいろの〇のアイコンがつきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671164/86d3f4a2-9152-d7f3-e665-5426a5c32d46.png)

女の子のスクリプトエリアに、下のようなコードを書いてみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671164/71fdbb48-36f0-b30f-3c08-2b6a1b780dc5.png)
緑のはたを押すと、女の子がリボンと一緒に動くように見えるはずです。
このとき、スプライトエリアのリボンのアイコンには、アイコンの右上のはいいろの〇マークの中には、下のようにまわるやじるしマークが書かれているはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671164/191055a7-8a54-7044-dc69-edf0ba6fb840.png)
まわるやじるしマークが書かれているときは、パーツのスプライトはアンカーのスクリプトと<b>いっしょにかいてん</b>します。

次に、リボンのスプライトアイコンの右上のはいいろの〇マークをクリックしてみましょう。まわるやじるしマークがちょくせんのやじるしになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671164/dc88654d-7dd0-3bc0-0e95-2a03d2708670.png)
この時、緑のはたを押すと、<b>女の子だけがまわり</b>、リボンはまわらなくなります。（よく見えない場合は、まつ時間を０．５びょうにしてみてください）
もちろん、リボンのスプライトのスクリプトエリアに「まわる」などのブロックをおくと、リボンだけがまわります。

アンカーのスプライトをクローンしたときは、パーツのクローンも<b>いっしょに</b>クローンされます。また、アンカーのいちや大きさをかえると、パーツも<b>いっしょに</b>いちがかわったり、大きくなったりします。

<a href="https://qiita.com/wordplugin/items/4158def39e181110c5bb">戻る</a>
全てのリクエストに502を返すアプリ

# はじめに

メンテナンス中にすべての要求に対して 502 を返すアプリが欲しくなった。
普通は NGINX でやらせるだろうけれど、実験的に ASP.NET Core で作ってみた。

# プロジェクトの作成

とりあえず空のWebプロジェクトを作って、

```sh
❯ dotnet new web -o allways502
❯ cd allways502
```

元からある `app.MapGet` をコメントにして、特定のステータスを返す Run デリゲートを追加する。

```cs:Program.cs
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// app.MapGet("/", () => "Hello World!");
app.Run(async context =>
{
   context.Response.StatusCode = StatusCodes.Status502BadGateway;
   await context.Response.WriteAsync("Hello BadGateway");
});

app.Run();
```

アプリを起動して、

```
❯ dotnet run
ビルドしています...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: https://localhost:7231
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5161
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: C:\LocalRepo\sugiyama\Sandbox\allways502\
```

リクエストすると、どんな URL でも 502 が返ってくる

```sh
❯ curl --dump-header - https://localhost:7231
HTTP/1.1 502 Bad Gateway
Date: Mon, 07 Mar 2022 05:09:08 GMT
Server: Kestrel
Transfer-Encoding: chunked

Hello BadGateway

❯ curl --dump-header - https://localhost:7231/abc
HTTP/1.1 502 Bad Gateway
Date: Mon, 07 Mar 2022 05:09:18 GMT
Server: Kestrel
Transfer-Encoding: chunked

Hello BadGateway
```

# おわりに

ngrok を使って公開してやれば、誰でもアクセスできるサーバーの出来上がり！
SQLの4大命令

# SQLの４大命令
SQLの４大命令は以下の４つです。

1```SELECT```
2```UPDATE```
3```DELETE```
4```INSERT```

この４つの命令の後さらに細かいデータ操作ができるように色々と追加で知っていくことがあります。

簡単い図に表すと以下のようになります。

|命令 | 各命令|絞り込み|検索結果の加工|
|:------|-------|----------|:----------|
|SELECT|列名・・FROM テーブル名　　|WHERE~　　　|その他,修飾|
|UPDATE|テーブル名　SET列名　=　値　|WHERE~　　|その他,修飾|
|DELETE|FROM        テーブル名| WHERE~    | その他,修飾|
|INSERT|INTOテーブル名(列名)VALUES(値・・)|WHERE~  |その他,修飾|

>引用　すっきりわかるSQL入門より
この４つが分かれば命令文の雛形が作くれます。
以下で４大命令をそれぞれ説明していきます。

# SELECT文
SELECTは```データの検索をする命令です。```

```sql
SELECT 列名・・　　　          --この列のデータを検索しろ
　　　　　　FROM  　テーブル名      --このテーブルから
(WHERE修飾)　　　　　
(その他の修飾)　　　　　　　　　　　　　　　　　　　　　
```
⚫︎補足
修飾は無しでもいい

例えば野球部員のデータベースの３年生のデータを取得するとします。

```sql
SELECT 体重,身長,ポジション
FROM   ３年生　--3年生テーブル
```
sqlを実行すると

|体重|身長|ポジション|
|:--|--:|:--|
|70|180|ピッチャー|
|78|177|キャチャー|
|75|185　|ファースト|
|63|175　|ショート|
|65|179　|センター|

ざっくりですがこんな感じになると思います。

●```ASで別名を定義```
列名やテーブル名の指定では```『AS+キーワード』```で別名を定義できます。


# UPDATE文
UPDATEは```データを更新して書き換える命令です。```

```sql
UPDATE テーブル名　　--このテーブルを更新して
　　 SET 列名1 = 値1, 列名2 = 値2 --この列をこの値で
(WHERE 修飾)
```

```sql
UPDATE 3年生
SET ポジション = サード
WHERE 身長　= 185
```
これで身長185の選手のポジションがサードに書き代わります。(上の表)

|体重|身長|ポジション|
|:--|--:|:--|
|70|180|ピッチャー|
|78|177|キャチャー|
|75|185　|ファースト|
|63|175　|ショート|
|65|179　|センター|

# DELETE
DELETEは```テーブルにある行、データを削除する命令です。```

```sql
DELETE   --削除しろ
FROM  テーブル名　　--このテーブル情報を
WHERE 修飾　
```

上の表のピッチャーの選手を消すには下のようになります。

```sql
DELETE FROM 3年生
WHERE ポジション　= 'ピッチャー'
```

ちなみに

```sql
DELETE FROM ３年生
```
これをやると３年生のデータが全部消えてしまいます。


# INSERT
INSERTは```テーブルに新しいデータを追加する命令です。```
基本この命令ではWHEREは使わないみたいです。

⚫︎INSERT文に基本構文

```sql
INSERT INTO  テーブル名　　　--このテーブルに
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　--追加しろ(INSERT)
　　　　(列名A、列名B、列名C・・)　　　--この列に
VALUES　　　(値A,値B、値C・・)　　--このデータを
```


```sql

INSERT INTO 3年生
       ( 出身,日付,握力) 
    VALUES ('静岡','2020-12-10',60)
```
で実行すると


|体重|身長|ポジション|
|:----|---:|:--|
|70|180|ピッチャー|
|78|177|キャチャー|
|75| 185　|ファースト|
|63| 175　|ショート|
|65| 179　|センター|










# 注意
***末尾にはセミコロンで文の終了***を表します。
これがないと動かなかったりしました。

```sql
SELECT * 
FROM ３年生;　　３年生はテーブル名;
```



⚫︎参考資料
https://www.amazon.co.jp/%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8BSQL%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E3%83%89%E3%83%AA%E3%83%AB222%E5%95%8F%E4%BB%98%E3%81%8D-%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E4%B8%AD%E5%B1%B1%E6%B8%85%E5%96%AC/dp/4295005096
Reactでアプリを作成しました【13】【Website with Bootstrap】

## 環境の準備

①ターミナルでreactアプリケーションを作成する。

```
$ npx create-react-app <プロジェクト名>
% cd <プロジェクト名>
% npm start
```

② 必要なパッケージをインストールする。

```
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
```

```public/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <!-- Bootstrap cdn-->
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
      crossorigin="anonymous"
    />
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>
```

コンポーネント・ファイル構成

```
 src
  ├── components
      └── guitar
          ├── Guitar.css
          └── Guitar.js
  ├── App.css
  ├── App.js
  ├── index.css
  ├── index.js
```
Power Apps Portals の認証ユーザーを作成し、権限を付与する

こんにちは。日本マイクロソフトの向井です。
こちらの記事では、Power Apps Portals の認証ユーザーを作成し、権限を付与する方法をご紹介します。

Power Apps Portals にサインインするユーザーをポータルユーザーと呼びます。
ポータルユーザーはDataverse の取引先担当者テーブルで管理されます。
ポータルユーザーが所属する組織、部署、チームなどは取引先企業テーブルで管理することができます。

Power Apps Portals の認証の方法は大きくわけると３種類あります。
①Azure AD 認証（推奨）
②外部接続プロバイダー（推奨）
③ローカル認証（非推奨）
です。

今回はAzure AD 認証を使用しました。

# 1. ポータルユーザーを作成する
まず、ポータルユーザーを作成します。今回は簡単のためポータルサイトからユーザーを作成しました。

ポータルにアクセスし、サインインをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/4ab02c2f-ea03-8cd5-7a5f-3c14e1526142.png)

Azure AD を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/7043be00-56d5-a178-af47-b63f8e6154eb.png)

組織の代表として同意にチェックを付けると、今後組織内のユーザーがサインインする際にこちらの確認画面をスキップできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/0f88b0a9-5d17-e4c7-e6d7-e0b4403253a7.png)

ユーザー情報を登録します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/20026387-6ca0-778c-327a-d8e22b91945e.png)

下の方にスクロールし、更新をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/d9ee8d50-1438-05bc-e862-e1e0c26dc20a.png)

# 2. ポータルユーザーにWebロールを付与する
次にポータルユーザーにWebロールを付与します。
ポータルユーザーにWeb ロールを付与することで、制限付きのページ（サインインしないと見れないページ）を閲覧させることができます。
Web ロールについては以下の記事を参考にしてください。
[ポータルの Web ロールの作成](https://docs.microsoft.com/ja-jp/powerapps/maker/portals/configure/create-web-roles)

Power Appsの画面を開き、Dataverse＞テーブル＞取引先担当者に移動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/b30dc04b-07c2-0f4c-ea66-de3dd854a8ae.png)

データの列を見ると、先ほどポータルから作成したユーザーのデータが保存されているのを確認できます。
レコードを選択してレコードの編集をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/ba4c04fc-8e5c-3c63-b7e4-1fa928f52f7f.png)

関連＞Webロールをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/c0882e34-2c27-4fca-b870-ba787aee8780.png)

こちらの画面で、ポータルのデータへのアクセスを制御するWebロールを付与できます。
今回は、既存のWebロールの追加をクリックし、管理者ロールを選択して追加をクリックします。
この時正しいポータルの権限を付与するように気を付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/874907a5-8a21-b4fe-e76f-059e10b8847a.png)

Webロールが追加されたのを確認して、保存して閉じるをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/78f4439a-49a5-e689-18fc-a634a9587233.png)

ポータルユーザーにWeb ロールを付与することができました。
これで先ほど作成したユーザーは管理者の権限で見れるページにアクセスできるようになります。
macOSにHomebrewで導入したJenkinsでdockerコマンドを使うための設定

# はじめに
macOSにHomebrewでJenkinsを導入し、Jenkins pipelineでdockerコマンドを使用すると、以下のエラーが出てdockerコマンドが実行できませんでした。当記事では、この事象を解決する設定について記載します。

```bash
# エラー内容
docker: command not found
```


# 前提環境
- マシン：MacBook Pro （14インチ, 2021）（M1 Max, メモリ64GBモデル）
- OS：macOS Monterey 12.0.1
- Jenkins 2.334（Homebrewで導入）
- Docker CLIはHomebrewで導入済み

# 設定内容
Homebrewで導入したJenkinsで実行されるジョブの環境変数PATHは、macOSで使用しているユーザのPATHと異なります。そのため、dockerコマンドの場所をJenkins用に設定する必要があります。

まず以下のコマンドを実行して、dockerコマンドの場所を確認します。

```bash
which docker
```

次に、Jenkinsに対して設定していきます。

Apple Silicon（M1以降）のMacでは、Homebrewで導入したJenkinsは``/opt/homebrew/Cellar/jenkins/<バージョン番号>``に配置されますが、このディレクトリにある``homebrew.mxcl.jenkins.plist``ファイルを編集し、環境変数PATHを設定します。

私の環境では、dockerコマンドは``/opt/homebrew/bin``にあるので、以下のように設定します。

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    (中略)
	<key>EnvironmentVariables</key>
	<dict>
		<key>PATH</key>
		<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin</string>
	</dict>
</dict>
</plist>
```

上記の通りファイルを編集・保存した後、Jenkinsを再起動します。

```bash
brew services restart jenkins
```

以上です。
[GCP] 手動作成したリソースをTerraform管理するまでにやったこと

## はじめに
備忘録です（予防線）

また、本記事ではterraformerを使用していますが、万一を想定して`.tf`コード生成のみの目的で使用しています。
（2022年3月4日時点で、terraformの最新は`v1.1.7`に対し、terraformerの対応は`v0.13`）

## 環境
- クラウド先: GCP
- コード管理: github
- apply環境: CircleCI
- terraformバージョン
  - ci上コンテナ: v0.14
  - ローカル: v0.13 (後述)

## やったこと
### 手順1 terraformer導入(ローカル)
既にあるリソースをterraform管理したい場合、`terraform import`が一般的だと思います。
しかし、このコマンドでは、tfstateのみしか更新を行いません。

Webコンソール画面・terraformドキュメント・エディタを行き来して、`tf`コードを生成するのは大変です。

そこで、`.tf`コードを自動作成してくれるterraformerを用いました。

https://github.com/GoogleCloudPlatform/terraformer

brew環境だと、以下でインストールできます。

```
brew install terraformer
```

また、私の環境だとterraform v0.14以上だと動きませんでした(2022年3月4日時点)
以下記事にもあるように、v0.13を導入すると良いでしょう
https://dev.classmethod.jp/articles/terraformer-version-dependence/

### 手順2 安全な環境の作成
作業前に、既存環境を壊さない準備をします。
以下の作業を行いました。
- tfstateのバックアップ
- 一時的なバケットの作成（S3/GCS）（terraformer用）
- 一時的な作業用ディレクトリの作成
  - provider設定を引き継ぐ
  - tfstate管理先を、上記作成のバケットへ

### 手順3 terraformer実行
以下より、コード化したいリソースのterraformer上表記を調べます
https://github.com/GoogleCloudPlatform/terraformer/blob/master/docs/gcp.md

そして、既存環境の`.tf`コードを生成します。
（tfstate管理先が一時的なバケットであるディテクトリで）
```
terraformer import google --resources=gcs,iam --projects=<プロジェクト名>
```

また、`--resources`は*で全リソース取得できます


### 手順4 リファクタ
terraformerにより作成された`.tf`コードのうち、必要なものを持ってきます。
（tfstate管理先が本番を向いている、元々のディレクトリへの移動/コピー）

また、以下をリファクタします
- terraformリソース名（長い）
- 変数（いらないものがある）
- リソース自体（terraform管理したくないリソースが含まれていたりする）

### 手順5 terraform import

リソースブロック単位で`terraform import`を実行します
コマンド例は公式ドキュメントにあります

ここでは、service_accountを例にします。
https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account#import

```
terraform import google_service_account.<terraformリソース名> projects/<プロジェクト名＞/serviceAccounts/<service_accountのメール>
```


### 手順6 terraform plan
terraform planを行い、問題ないことを確認します
（差分が無い or 意図する差分しか出ていない）

### 手順7 githubへのmerge、terraform applyなど
これらの内容を反映させます

## おわりに
マサカリお待ちしております
python-pptx 使い方


# Pythonを用いてPowerPointを操作したい

python-pptx というライブラリを用いて、
PowerPoint 操作を行ったので、その記録として残します。

公式ドキュメント

https://python-pptx.readthedocs.io/en/latest/

## インストール
~~~
pip install python-pptx
~~~


## 必要な機能をインポート

~~~
import collections.abc # インポートしないとエラーが発生する
from pptx import Presentation # プレゼンテーションを作成
from pptx.util import Inches  # インチ
from pptx.enum.text import PP_ALIGN  # 中央揃えにする用
from pptx.util import Cm, Pt # センチ、ポイント
~~~

~~~
import collections.abc
~~~

上記のモジュールをインポートしないと
以下のエラーが発生します。

~~~
AttributeError: module 'collections' has no attribute 'Container'
~~~


## pptxファイルの読み込み
新規でPowerPointファイルを作成
~~~
ppt = Presentation()
~~~
既存のファイルを読み込む
~~~
ppt = Presentation(filepath)
~~~

## スライドレイアウトの読み込み
~~~
layout = ppt.slide_layouts[i]
~~~

インデックス番号によって、使用するスライドが異なります。

## 選択したスライドを追加
~~~
slide = ppt.slides.add_slide(layout)
~~~

## テーブルの挿入

~~~
table = slide.shapes.add_table(row, col, x_pos, y_pos, width, height).table
~~~

## 表のスタイルを変更する

~~~
tbl = table._graphic_frame.element.graphic.graphicData.tbl
style_id = '{E8B1032C-EA38-4F05-BA0D-38AFFFC7BED3}'  # GUIDはgithub参照
tbl[0][-1].text = style_id
~~~

参照する GUID

https://github.com/scanny/python-pptx/issues/27

表の幅を変更する。
例、columns[1] の幅を2インチに変更します。

~~~
table.columns[1].width = Inches(2)
~~~

## フォント関連設定
https://python-pptx.readthedocs.io/en/latest/api/text.html#font-objects

~~~
table.cell(0, 0).text_frame.paragraphs[0].font.size = Pt(16)

# フォントの種類を指定する。

table.cell(0, 0).text_frame.paragraphs[0].font.name = 'メイリオ' # フォント名を指定
table.cell(0, 0).text_frame.paragraphs[0].font.italic = True # イタリック
table.cell(0, 0).text_frame.paragraphs[0].font.underline = True # アンダーラインを引く

# フォントを中央揃えにする。

table.cell(0, 0).text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
~~~



## 作成したPowerPointを保存
~~~
ppt.save("./chart.pptx")
~~~

## 参考文献

https://www.shibutan-bloomers.com/python-libraly-pptx/988/


やはり英語のドキュメントが読めると、
かなり作業効率が上がりますね。

積極的に読んで英語に慣れていこうと思います。
vsftpdでちょっと焦ったお話

FileZillaでFTPにつなげようとしたところ、こんなエラーが
```
ECONNREFUSED - サーバーによって接続が拒否されました
```
先週まで接続できてたのになぜ

## ①原因を探る

#### ■AWSコンソールでインスタンスの状況を確認
インスタンスは動いてるのを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596047/7e7c47bd-b22f-7c8f-9cad-7584164219d4.png)

#### ■/etc/httpd/logsを確認

```error.log
AH00171: Graceful restart requested, doing restart
```

「むむ？先週再起動してるぞ？」

## ➁もしかして....
#### `vsftpd`ステータスのチェック
```
sudo systemctl status vsftpd

● vsftpd.service - Vsftpd ftp daemon
   Loaded: loaded (/usr/lib/systemd/system/vsftpd.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
```
`vsftpd`が動いてない！！
[※vsftpdとは](https://e-words.jp/w/vsftpd.html)

## ➂対応策と解決策

#### `vsftpd`を再起動
```
sudo systemctl restart vsftpd

● vsftpd.service - Vsftpd ftp daemon
   Loaded: loaded (/usr/lib/systemd/system/vsftpd.service; disabled; vendor preset: disabled)
   Active: active (running) since Mon 2022-03-07 12:55:24 JST; 2s ago
```

**このようなことが次も起こらないように、サービス自動起動有効化する。**
```
systemctl enable vsftpd.service
```
`systemctl` については[**こちら**](https://qiita.com/sinsengumi/items/24d726ec6c761fc75cc9)

## まとめ
普段当たり前のように使っているテストサーバーやFTPサーバでも、色々な設定がされていることで利便性が上がっていることをを改めて痛感しました。
自戒を込めて共有します。

## 参考サイト
https://xtech.nikkei.com/it/article/COLUMN/20140310/542302/
https://ja.stackoverflow.com/questions/72693/centos7%E3%81%8B%E3%82%89ftps%E3%82%B5%E3%83%BC%E3%83%90%E3%81%B8%E6%8E%A5%E7%B6%9A%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84
http://basicwerk.com/memoize2/index.cgi?ftp.lftp_ftps_connect.txt
https://jerome-ando.blog.jp/archives/ftp_over_ssl_with_lftp_command_ja.html
https://tomokazu-kozuma.com/how-to-install-and-use-lftp/
Tomcatにて外部参照を行っている場合にweb.xmlの解析エラーが発生する


Tomcatにて下記のようなエラーが発生している場合、
web.xmlで外部参照を利用している可能性があります。

````
java.io.FileNotFoundException: Could not resolve XML resource [null] with public ID [null], system ID　（後略）
````

この場合web.xmlで外部参照を利用している可能性があります。
詳しくは下記ページをご覧ください。

https://miyakoroom.blogspot.com/2018/09/servlet-webxml.html


ただ閉じた環境で利用するので別に外部参照してもいいよって場合、

context.xmlを以下のように書き換えます。

````xml
<Context>
````

````xml
<Context xmlBlockExternal="false">
````
オープンリゾルバ とは

## 勉強前イメージ

オープン？誰でも使えるってこと？

## 調査

### まずリゾルバとは？

- スタブリゾルバ

リゾルバとはDNSの名前解決のためのクライアントのことで、
ドメインからIPを検索したり、IPからドメインを検索したりします。

- フルサービスリゾルバ(キャッシュDNSサーバ)

クライアントから来たDNSの応答を権威サーバに反復検索を行い、
最終的に応答を返す役割のDNSキャッシュサーバになります。

上記の関係性としては以下になります。

![Untitled Diagram.drawio - diagrams.net - Google Chrome 2022-03-07 12.46.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/b1302803-02be-343e-23ff-483ced982006.png)

### では、オープンリゾルバとは？

上記のフルサービスリゾルバの役割で、
インターネット上のどのクライアントからの名前解決要求でも実行してしまう状態のサーバ、またはネットワーク機器のことを指します。
通常では、自分のネットワーク内にある端末からの問い合わせ受け付けて返すが、アクセス制限を行っていないとこのような動作になり、オープンリゾルバと呼ばれる。
DNSの問い合わせや応答は主にUDPを使用しているため、どの機器からの問い合わせにも応答できてしまうと
DNSキャッシュポイズニング攻撃や [DNSリフレクター攻撃](https://qiita.com/miyuki_samitani/items/3df8e430e318ea4fd14d) など攻撃のの踏み台に使用される可能性がある。
そのため、理由がない限り基本的にはオープン設定でリゾルバは運用すべきではない

しかし、管理されたオープンリゾルバを提供しているサービスもあります。
それに関しては、パブリックリゾルバと呼ばれています。

## 勉強後イメージ

大体放置されてるサーバとか適当に作ったやつとかありそうね。
危ない・・・・

## 参考

- [フルサービスリゾルバー（キャッシュDNSサーバー）](https://jprs.jp/glossary/index.php?ID=0158#:~:text=%E3%82%B9%E3%82%BF%E3%83%96%E3%83%AA%E3%82%BE%E3%83%AB%E3%83%90%E3%83%BC%EF%BC%88DNS%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88%EF%BC%89%E3%81%8B%E3%82%89,%E5%BF%9C%E7%AD%94%E3%81%A8%E3%81%97%E3%81%A6%E8%BF%94%E3%81%99%E3%83%AA%E3%82%BE%E3%83%AB%E3%83%90%E3%83%BC%E3%81%A7%E3%81%99%E3%80%82)
# AtCoder 向け C++ & Docker 環境構築

`Python`を使ってAtCoderを最近始めましたが、TLEにあまりにも悩まされたので、`C++`で挑むことにしました。そのときのDockerの環境構築方法について備忘録として残しておきます。

#### 環境構築の手順

筆者は以下の環境にて構築しました
* MacOS Big Sur 11.6.1
* Apple MacMini 2018 Intel Core i3

また、Docker for Desktopはインストール済みと言う前提で進めます。

#### 1. Dockerfileの作成

Dockerfileの中身は以下の通りです。

```Dockerfile
FROM ubuntu:latest

RUN apt update && \
    apt upgrade -y && \
    apt install -y build-essential

RUN mkdir /work
WORKDIR /work
```
これを以下のようなディレクトリに配置します。Dockerfileがある階層に`work`というフォルダを作成します。
```
.
┣━ Dockerfile
┗━ work/
```

#### 2. イメージをビルドしてコンテナ作成
上記のDockerfileを用いて環境構築を行います。
以下のコマンドを使ってコンテナ作成を行っていきます。
パスはDockerfileがある階層で行ってください。

* イメージビルド
```
$ docker image build . -t イメージ名
```
イメージ名は任意です。

* コンテナ立ち上げ
```
docker run -v "$(pwd)"/work:/work -it イメージ名  --name コンテナ名
```

コンテナ名は任意です。イメージはビルドしたときに指定したイメージ名を入力してください。

※以下はVSCodeの設定です。

#### 3. C++ファイルの実行ショートカットコマンドの設定

ショートカットを使って実行ができるように設定を行います。

##### 3-1. 拡張機能のインストール

以下の拡張機能をインストールしてください。

* [C/C++](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools)
* [C/C++ Clang Command Adapter](https://marketplace.visualstudio.com/items?itemName=mitaki28.vscode-clang)
* [Code Runner](https://marketplace.visualstudio.com/items?itemName=formulahendry.code-runner)

##### 3-2. ショートカットの設定

以下の画像のように「Code > 基本設定 > キーボードショートカット」を選択します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1726209/3a60730a-5ed6-d817-9a93-bc415c923086.png)
右上にある「キーボードショートカットを開く(JSON)」をクリックし、`keybindings.json`を開きます。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1726209/2accc375-704c-a04d-6d3a-878a15d2a098.png)
そして`keybindings.json`に以下のようにショートカットの設定を入力します。
例として`Command` + `N` によって実行できるようにしていますが、組み合わせは任意です。
```json
[
  {
    "key": "cmd+n",
    "command": "code-runner.run"
  }
]
```

##### 3-3. ショートカットの動作設定
VSCodeの設定を開き、右上にある「設定(JSON)を開く」をクリックし、`setting.json`を開きます。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1726209/089e0ff9-c0ab-8576-75da-d56dcbec4eea.png)
そして`setting.json`に以下のコードを追加します。
```json
{
  "clang.executable": "clang++",
  "code-runner.runInTerminal": true,
  "clang.cxxflags": [ "-std=c++14"],
  "code-runner.executorMap": {
    "cpp": "cd $dir && g++ -O2 -std=c++14 $fileName && ./a.out",
  }
}
```
##### 3-4. Dockerコンテナのリモート接続

以下の拡張機能をインストールしてください。
* [Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)

インストールできれば、以下の画面の「リモートエクスプローラ」を開きます。
先程作成したコンテナの「Attach to Container」をクリックします。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1726209/d8cf7d5e-24e1-ef26-b6a6-a5a0cd68e878.png)
そして、ディレクトリの選択を求められるので、`/work/`を選択します。
すると、コンテナの中に入った新規ウィンドウが開きます。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1726209/eaf7efa1-f4d7-9a30-7046-da1814ad749a.png)
ここに`.cpp`ファイルを適当に作成し、そしてコマンドを入力して試しに実行してみます。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1726209/dcdd0ce4-176a-0bc1-fc53-0fb3ce762a31.png)
ターミナルにショートカットが入力され、正しく動作すれば設定完了です。

#### まとめ
本記事では`C++`のコンテナ作成と実行のショートカット設定を行いました。
上記の方法で何かエラーが起きたなどがあればご連絡いただけると幸いです。
以上になります。
Delta Lakeのアイソレーションレベル

[Isolation levels \| Databricks on AWS](https://docs.databricks.com/delta/optimizations/isolation-level.html) [2021/6/11時点]の翻訳です。

:::note alert
本書の内容は古くなっています。[Databricksにおけるアイソレーションレベルと書き込みの競合](https://qiita.com/taka_yayoi/items/62a581c20ab4096a990b)をご覧ください。
:::

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

テーブルのアイソレーションレベルは、同時トランザクションによる変更から、どのトランザクションを分離すべきかの度合いを定義します。DatabricksのDelta Lakeでは、2つのアイソレーションレベルをサポートしています。SerializableとWriteSerializableです。

- **Serializable**: 最も強いアイソレーションレベルです。コミットされる書き込みオペレーションと全ての読み込みが[シリアライズ可能](https://en.wikipedia.org/wiki/Serializability)であることを保証します。テーブル履歴で確認されるのと同じ結果を生成する、一度に一回のポリシーに基づく処理の実行に順序が存在する場合に限りオペレーションは許可されます。書き込みオペレーションにおいては、テーブルの履歴と全く同じ順序で実行されます。
- **WriteSerializable(デフォルト)**: Serializableよりも弱いアイソレーションレベルです。書き込みオペレーションのみがシリアライズ可能であることを保証します。しかし、これは[スナップショット](https://en.wikipedia.org/wiki/Snapshot_isolation)アイソレーションよりも強いものです。WriteSerializableは、多くの一般的なオペレーションにおいてデータの一貫性と可用性の優れたバランスを提供するため、デフォルトのアイソレーションレベルとなっています。

    このモードでは、Deltaテーブルの中身はテーブル履歴で確認される一連のオペレーションに期待されるものと異なる場合があります。これは、このモードにおいては、特定の組み合わせの同時書き込み(例えば、オペレーションXとオペレーションY)を、履歴上はXのあとにYがコミットされたように表示されたとしても、YがXの前に実行された(すなわち、これらの間でシリアライズが可能)ような結果となるように処理を進めることを許可します。この並び替えを許可しないようにするためには、[テーブルアイソレーションレベル](#アイソレーションレベルの設定)をSerializableに設定して、エラーを起こすようにします。

読み込みオペレーションは常にスナップショットのアイソレーションを使用します。この書き込みアイソレーションレベルは、readerが履歴によれば「存在したことがない」テーブルのスナップショットを参照できるかどうかを決定します。

Serializableレベルにおいては、readerは常に履歴に準拠するテーブルのみを常に参照します。WriteSerializableレベルにおいては、Deltaログに存在しないテーブルを参照する場合があります。

例えば、長時間削除を行なっているtxn1と、txn1によって削除されたデータをインサートするtxn2を考えてみます。txn2とtxn1が完了し、履歴順に記録されたとします。履歴によれば、txb2によってインサートされたデータはテーブルに存在すべきではありません。Serializableレベルでは、readerはtxn2によってインサートされたデータを参照することはありません。しかし、WriteSerializableレベルでは、readerはある時点でtxn2によってインサートされたデータを参照する場合があります。

どのタイプのオペレーションが、それぞれのアイソレーションレベルで競合するのか、潜在的なエラーを引き起こすのかについては、[コンカレンシーコントロール](https://qiita.com/taka_yayoi/items/94db8363720687d17d6e)を参照ください。

# アイソレーションレベルの設定

`ALTER TABLE`コマンドを用いてアイソレーションレベルを設定します。

```sql:SQL
ALTER TABLE <table-name> SET TBLPROPERTIES ('delta.isolationLevel' = <level-name>)
```

ここで、`<level-name>`は`Serializable`か`WriteSerializable`となります。

例えば、デフォルトの`WriteSerializable`から`Serializable`に変更するには、以下を実行します。

```sql:SQL
ALTER TABLE <table-name> SET TBLPROPERTIES ('delta.isolationLevel' = 'Serializable')
```

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)