himorogiの日記

主にプログラミングに関することなど。少々ハード(電子工作)についても。

PowerShell v7.3.0 Release

M1 Mac mini に変えて、PowerShell インストールしようとしたら、最近まで Rosetta 2 必須だった。
特に理由はないけど Rosetta 2 入れるのが嫌だったので、今まで M1 Mac miniPowerShell は我慢してきた。

でも辛抱堪らず、先ほど PowerShell インストールしたら、数時間前に update されてて遂に Rosetta 2 不要になってた模様。

irbRuby 使ってたりしたが、やはり手慣れた PowerShell 使えるのはありがたい!

【macOS】【続】PowerShell から SQLite を使うための備忘録・補遺【.import】

.import で CSV ファイルを扱う話の続き…

何度も書いたように、SQLite 内部では CSV 形式では格納されていないため、CSV 形式でやりとりするためには、.separator で区切り文字を切り替えるか、SQLite 外部で CSV 形式に変換する必要がある。
実は、.separator の他に、.mode csv でも同様の指定ができる。
.mode csv も .separator と同様に、セッション中有効なので、複数行のステートメントでコマンドを渡せば、.mode 以降のステートメントでは、CSV 形式が適用(mode)されて入出力ができる。

そこで、.separator と .mode による切り替えが全く同様なのか検証してみた。

まず .separator '|'

PS /Users/hoge/devPwsh> @"
>> DELETE FROM Proverb;
>> .separator ,
>> .import ./Proverb.csv --skip 1 Proverb      
>> SELECT * FROM Proverb;
>> "@ | sqlite3 ./Proverb.db $_
1,厩戸皇子,以和爲貴
2,釈迦,天上天下唯我独尊
3,孔子,有朋自遠方来不亦楽乎
4,杜甫,国破山河在
PS /Users/hoge/devPwsh>

次に .mode csv

PS /Users/hoge/devPwsh> @"
>> DELETE FROM Proverb;
>> .mode csv   
>> .import ./Proverb.csv --skip 1 Proverb      
>> SELECT * FROM Proverb;
>> "@ | sqlite3 ./Proverb.db $_
1,"厩戸皇子","以和爲貴"
2,"釈迦","天上天下唯我独尊"
3,"孔子","有朋自遠方来不亦楽乎"
4,"杜甫","国破山河在"
PS /Users/hoge/devPwsh>

そしてて SQLite デフォルト形式を convertfrom-csv と convertto-csv で変換した場合。

PS /Users/hoge/devPwsh> @"
>> DELETE FROM Proverb;
>> .import ./Proverb.csv --csv --skip 1 Proverb
>> SELECT * FROM Proverb;
>> "@ | sqlite3 ./Proverb.db $_ | convertfrom-csv -delimiter '|' | convertto-csv
"1","厩戸皇子","以和爲貴"
"2","釈迦","天上天下唯我独尊"
"3","孔子","有朋自遠方来不亦楽乎"
"4","杜甫","国破山河在"
PS /Users/hoge/devPwsh>

このように、文字列については double-quote で囲われる方が望ましいので .separator は避けるべきかもしれない。
また、Powershell で読み込むのではなく、一旦 CSV ファイルとして結果を格納したいのなら、convertfrom-csv と convertto-csv 経由だと数値データも double-quote で囲われるため、使い方に留意すべきだろう。

何にせよ .separator も .mode も、convertfrom-csv と convertto-csv で変換してしまえば、結果は同一。

PS /Users/hoge/devPwsh> @"
>> DELETE FROM Proverb;
>> .separator ,
>> .import ./Proverb.csv --skip 1 Proverb
>> SELECT * FROM Proverb;
>> "@ | sqlite3 ./Proverb.db $_| convertfrom-csv | convertto-csv 
"1","厩戸皇子","以和爲貴"
"2","釈迦","天上天下唯我独尊"
"3","孔子","有朋自遠方来不亦楽乎"
"4","杜甫","国破山河在"
PS /Users/hoge/devPwsh>
PS /Users/hoge/devPwsh> @"
>> DELETE FROM Proverb;
>> .mode csv
>> .import ./Proverb.csv --skip 1 Proverb
>> SELECT * FROM Proverb;
>> "@ | sqlite3 ./Proverb.db $_ | convertfrom-csv | convertto-csv 
"1","厩戸皇子","以和爲貴"
"2","釈迦","天上天下唯我独尊"
"3","孔子","有朋自遠方来不亦楽乎"
"4","杜甫","国破山河在"
PS /Users/hoge/devPwsh>

【macOS】PowerShell から SQLite を使うための備忘録・補遺【.import】

これは 2021 年 12 月 1 日の以下の記事の補足・補遺です。

macOSPowerShell から SQLite を使うための備忘録【.import】 - himorogiの日記himorogi.hatenablog.com

尚、前回、myFirst.db としてたところは、今回 Proverb.db にリネームしている。

さて、前回 .import の実例として以下のソースを掲示した。

importProverb.ps1

@"
CREATE TABLE Proverb ( id, name, phrase );
.separator ,
.import ./Proverb.csv Proverb
SELECT * FROM Proverb;
"@ | sqlite3 ./Proverb.db $_

上のコードは、テーブルの生成・セパレータの変更・インポート実行を一気に行なっている。
ps1 ファイルに記述して、外部コマンドとして実行している。

前回にも指摘したが、留意すべき点として… .import する CSV ファイルにヘッダーを含むと .import はそのままでは先頭行もデータと見做してしまう。

実は、.import には複数のオプションがあり、--skip N (N は任意の数、読み飛ばす行数を指定)で、ヘッダーを読み飛ばすことができる。
SQLite は長年簡易なポケットリファレンスを見ながら決め打ちで使ってたため(このような場面で usege が出てくることもなく)、--skip オプションがあることに気が付かなかった。

従って、前回やったように、別途 CSV ファイルからヘッダーを削除した中間ファイルを作成する必要はない。

この場合、.import の行は以下のように記述すれば、CSV ファイル先頭行のヘッダーを無視できる。

.import ./Proverb.csv --skip 1 Proverb

また SQLite では、セパレータにはデフォルトで '|' が使われており、冒頭のソースコードは .separator コマンドで、CSV ファイルのまま読み込めるようセパレータを変更している。

.import コマンドには、--skip N 以外にもオプションがあってインポートするファイルの形式を色々指定でき、--csv を指定すれば、.separator を使わずとも CSV ファイルのまま読み込める。
今回は .ps1 ファイルを作成せず REPL から直接実行してみた。

尚、前回インポートしたデータが残ってるので、最初に DELETE を実行している。

PS /Users/hoge/devPwsh> @"
>> DELETE FROM Proverb;
>> .import ./Proverb.csv --csv --skip 1 Proverb
>> SELECT * FROM Proverb;
>> "@ | sqlite3 ./Proverb.db $_
1|厩戸皇子|以和爲貴
2|釈迦|天上天下唯我独尊
3|孔子|有朋自遠方来不亦楽乎
4|杜甫|国破山河在
PS /Users/hoge/devPwsh> 

.separator によるセパレータの変更は、セッション中は有効なので、ヒアドキュメントにより複文を実行した際は SELECT 文の結果も CSV の体裁になっていたが、--csv オプションによる CSV インポートでは、CSV を内部形式に変換するのみ(※ 2022/07/04 注:というより .import ステートメント中のみ有効)なので、ヒアドキュメント中の直後に実行した SELECT 文の結果でも CSV の体裁にはならない。

PowershellSQLite の間で、データを CSV 形式でやり取りするなら、.import やSQL文実行の都度 .separator を記述する必要がある。
ただ、自分的には、モーダルな .separator を毎回実行するより、以下の方が機能的に明解なので、こちらでやろうと思う。

ここでも前回インポートしたデータを消すために最初に DELETE を実行している。

PS /Users/hoge/devPwsh> @"
>> DELETE FROM Proverb;
>> .import ./Proverb.csv --csv --skip 1 Proverb
>> SELECT * FROM Proverb;
>> "@ | sqlite3 ./Proverb.db $_ | convertfrom-csv -delimiter '|' | convertto-csv 
"1","厩戸皇子","以和爲貴"
"2","釈迦","天上天下唯我独尊"
"3","孔子","有朋自遠方来不亦楽乎"
"4","杜甫","国破山河在"
PS /Users/hoge/devPwsh> 

一見煩雑だけど Powershell に直接読み取る場合は、convertto-csv 不要だし、convertfrom-csvPOSIX 経由で SQLite とやり取りする限り必要なので

  • .separator の代わりに .import で --csv オプションを使う
  • .separator の代わりに convertfrom-csv で -delimiter '|' を指定する

だけなら、結果的に手間は同じ。

M1 Mac mini と Groovy:SQLite を使う#1

新しく script 言語を覚えるときに、SQLite 周りから始めることが多い。
なぜなら、script 言語の機能にはさほど通宵しなくても、とりあえず面倒な部分は SQLite で片付くので、いきなり実用的な処理が書ける。
そうやって実務で成果を稼ぎながら、空いた時間を script の学習に割ける、という一挙両得。

groovy は SQL サポートがあり、SQLiteJDBC ライブラリ経由で利用できる。
ただ、最初の頃、動作確認するのに、bug なのか仕様なのか振り分けるために、外部コマンドとして SQLite を起動する方法も確認しておきたい。

というわけで、

'SQLite3 Proverb.db "CREATE TABLE Proverb ( id, name, phrase );"'.execute()

これを groovyConsle から実行した結果が以下

groovy> 'SQLite3 Proverb.db "CREATE TABLE Proverb ( id, name, phrase );'.execute() 
Result: Process[pid=36926, exitValue="not exited"]

ls した結果、Proverb.db は生成されていた。
確認のため、terminal から SQLite に入ってみる…

hoge ~ % sqlite3 Proverb.db
SQLite version 3.37.0 2021-12-09 01:34:53
Enter ".help" for usage hints.
sqlite> .tables
sqlite> .schema
sqlite>

.tables も .schema も戻りはブランクなので、CREATE 文が実行されてない。
多分、外部コマンド実行の際に第二パラメータが引き渡されてない。

外部コマンドは、文字列の他に、配列として指定することもできるので、今度は配列で渡してみた。
※予め rm Proverb.db で db ファイルは削除済み

["SQLite3","Proverb.db","CREATE TABLE Proverb ( id, name, phrase );"].execute()

再び groovyConsle から実行した結果が以下

groovy> ["SQLite3","Proverb.db","CREATE TABLE Proverb ( id, name, phrase );"].execute() 
Result: Process[pid=35729, exitValue="not exited"]

確認のため、terminal から SQLite に入ってみる…

hoge ~ % sqlite3 Proverb.db
SQLite version 3.37.0 2021-12-09 01:34:53
Enter ".help" for usage hints.
sqlite> .tables
Proverb
sqlite> .schema 
CREATE TABLE Proverb ( id, name, phrase );
sqlite>

今回は、第二パラメータの SQLクエリを正常に実行できていた。
外部コマンドで SQLite を弄れると何が便利かというと .comand が利用できる。

SQLite で .schema を実行し、結果を受け取りたいので .execute().text を使う。

["SQLite3","Proverb.db",".schema"].execute().text

groovyConsle から実行した結果が以下

groovy> ["SQLite3","Proverb.db",".schema"].execute().text 
Result: CREATE TABLE Proverb ( id, name, phrase );

Mac mini と Groovy 3本目

Groovy のやり直し中。最新の情報は日本語では頼りなくて、ほぼ英語頼み…というのは、40年昔に Micorprocessor 弄り始めた頃に比べ、今は Google 翻訳や DeepL 使えるから全然苦ではないのだけど…
Groovy も前回弄ってたころから随分間が空いてたので忘れてしまったことも多いのに、Groovy 3 になって新しく覚えることも増えてちょっと大変。
その上 Groovy から Java 呼べるので、最新の Java の仕様もフォローしないといけない感じ?

M1 Mac mini と Groovysh

Groovy の REPL 環境である groovysh を起動してみたら、警告でて反応帰ってこない…

警告: ansi will be disabled because an error occurred while installing ansi: Could not load library. Reasons: [no jansi in java.library.path: /Users/hoge/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:., Can't load library: /var/folders/bj/gtykn1553438qf4qxv6fxkb00000gn/T/libjansi-64-4582434779276600134.jnilib]

検索してみたら、どうも Apple Silicon 版では JINI libraries が抜けてるせい…とか…