Fujitsu製RDB Symfowareの.NET Data Providerを使ってSQLを発行するPowerShellコマンドを作ってみる

#1．はじめに
　本記事は、Fujitsu製商用リレーショナルデータベースシステムであるSymfowareで構成されたデータベースに対してSQLを投げてデータオブジェクトで保持してデータアクセスを容易にしようというテーマとなっています。

##1.1．記事の構成
　本記事の構成は以下の通りです。

 [1. はじめに](https://qiita.com/koichiro-h/items/bfcba194f756bfa9f734#1はじめに)
    [1.1. 記事の構成](https://qiita.com/koichiro-h/items/bfcba194f756bfa9f734#11記事の構成)

 [2. まえおき](https://qiita.com/koichiro-h/items/bfcba194f756bfa9f734#2まえおき)
    [2.1．Symfowareとは](https://qiita.com/koichiro-h/items/bfcba194f756bfa9f734#21symfowareとは)
    [2.2. ブログ記事を書いた背景](https://qiita.com/koichiro-h/items/bfcba194f756bfa9f734#22-ブログ記事を書いた背景)
    [2.3．WebDBToolは多機能](https://qiita.com/koichiro-h/items/bfcba194f756bfa9f734#23webdbtoolは多機能)
    [2.4．なぜ.NETなのか](https://qiita.com/koichiro-h/items/bfcba194f756bfa9f734#24なぜnetなのか)

 [3. 本題](https://qiita.com/koichiro-h/items/bfcba194f756bfa9f734#3本題)
    [3.1．Execute-SymfoSQLコマンドレッドの作成](https://qiita.com/koichiro-h/items/bfcba194f756bfa9f734#31execute-symfosqlコマンドレッドの作成)
    [3.2．SQL実行結果で色々と遊ぶ](https://qiita.com/koichiro-h/items/bfcba194f756bfa9f734#32sql実行結果で色々と遊ぶ)

 [4. さいごに](https://qiita.com/koichiro-h/items/bfcba194f756bfa9f734#4さいごに)

---


#2．まえおき
　このセクションでは主に事前に説明したい部分を書いています。サクッと本題だけ参照したい方は本セクションを飛ばして[セクション3 本題](https://qiita.com/koichiro-h/items/bfcba194f756bfa9f734#3本題)からご覧ください。

##2.1．Symfowareとは
　大雑把に説明すると、Oracleライクなリレーショナルデータベースを構築出来る統合データベースシステムです。コマンド体系やSQL構文はOracleに似ていますが、所々の特徴は異なっておりFujitsu独自の体系となっています。他のRDB同様、WebUIからデータベースの構築や運用が可能です。
　[Symfoware詳細はこちら](http://software.fujitsu.com/jp/manual/manualindex/p14000455.html)

##2.2. ブログ記事を書いた背景
　業務ではじめてSymfowareをガッツリいじる機会に触れ(と言ってもSELECT複合文のみ)WebDBToolの標準GUIが何とも微妙な使い勝手だったため、コマンドラインで手軽にSQLを発行できるコマンドレッドを作ってみた。

　具体的にGUIの何が使いづらいかというと以下の通り

  - Webログインが面倒(と言ってもシンプルなユーザ認証)
  - select実行結果がWebページ上のTABLEに最大50件ずつしかでてこない
  - 非同期処理ではないため都度ページがリフレッシュされる
  - 当然、次の50件を見ようとしてもページがリフレッシュされる

適当なテスト環境のため３件しかデータ入れてませんが、画面イメージ置いときますね(σ･ω･)σ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/136977/7caf51a3-d6ae-e84b-30bd-75a88ed2d2a2.png)

##2.3．WebDBToolは多機能
　こう書くとWebDBToolは使えないと思われても困るので色々と補足しておくと、WebDBToolとしては以下の機能を搭載しています。

  - コマンドラインの提供
  - リモートコマンドラインの提供
  - JDBCドライバの提供
  - ODBCドライバの提供
  - .NET Data Providerの提供
  - WebScriptと拡張タグの提供
  - WebUIの提供(WebScriptと拡張タグによるカスタムが可能)

　このように、様々なインタフェースが用意されており、非プログラマでも使いこなせば運用を楽にする土壌は揃ってます。(あくまでも使いこなせれば、の話です)

　さすが日本でそれなりのシェアを誇る商用RDBですね！(これくらいで良いでしょうか...)

##2.4．なぜ.NETなのか
　前項の通り多様なインタフェースからなぜ.NETを選んだのかというと以下のような理由があります。

  - コマンドラインではダメなのか？

　　👉実行結果をオブジェクトにしてプログラム内で有効利用したかった

  - WebUIをカスタマイズ

　　👉むしろこっちの方が時間かかりそう...


...といった具合です。ではSelect文だけなのであれば使わない.NETクラス群も多いためODBC接続ではダメなのか？という声が聞こえてきそうですね(^.^)


![VIP終わったな終わってんのはお前だよ](https://iwiz-chie.c.yimg.jp/im_siggeEqoXwhgie9KR.9PPMNFvQ---x320-y320-exp5m-n1/d/iwiz-chie/ans-272325549)


...おっしゃる通りorz...
実ははじめはODBC接続を試みたのですが、64bitのwindows7環境では上手くSymfowareのODBC接続が出来なかったので諦めました..._(:3 」∠ )_ 

原因はドライバとODBCのシステム環境が異なるか、DSNの指定が間違ってる(←おい...)かよく分からなかったのですが、.NETに逃げて上手くいったので良しとします。


#3．本題
##3.1．Execute-SymfoSQLコマンドレッドの作成

　Execute-SymfoSQLコマンドは、SQL文字列を必須引数、XML保存用ファイルパスを任意引数に取るシンプルなコマンドとしました。なお、冒頭のGAC読み込み部分の4行の先頭にスペースが入ってますが、Qiitaの仕様なのか、半角スペース以外の何かしらの文字を挿入しないと表示されなかったため全角スペースを付与しています。

```powershell

　[System.Reflection.Assembly]::LoadWithPartialName("Fujitsu.Symfoware")
　[System.Reflection.Assembly]::LoadWithPartialName("Fujitsu.Symfoware.resources")
　[System.Reflection.Assembly]::LoadWithPartialName("policy.1.80.Fujitsu.Symfoware")
　[System.Reflection.Assembly]::LoadWithPartialName("System.Data")

function Execute-SymfoSQL() {
    param(
        [Parameter(ValueFromPipeline=$true,Mandatory=$true)]
        [String[]]$sql,
        [Parameter(ValueFromPipeline=$false,Mandatory=$false)]
        [String[]]$xmlpath
    )

    #Connectionの確立
    $connString = "Addr=127.0.0.1;Port=2050;UID=user01;Pwd=@passwd;Database=MYDB;schema=MY_SCHEMA"
    $conn = New-Object Fujitsu.Symfoware.Client.SymfowareConnection($connString)
    $conn.Open()

    #SQL実行結果のData化
    $adp = New-Object Fujitsu.Symfoware.Client.SymfowareDataAdapter($sql, $conn)
    $dst = New-Object System.Data.DataSet
    $adp.Fill($dst,"testTable")

    #xmlファイルの保存処理
    if ( $xmlpath -ne $null ) {
        $fs = New-Object -ComObject Scripting.FileSystemObject
        if ( $fs.FolderExists($fs.GetParentFolderName($xmlpath)) ) {
            $dst.WriteXml($xmlpath)
        }
    }

    #リソース解放
    $adp.Dispose()
    $conn.Close()

    #Dataを返却
    return $dst

}
```
なお、*xmlpath*引数にファイルパスを渡すと、SQL実行結果をxmlに保存します。本記事では取り扱わないため割愛します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/136977/b416fd1e-b8c4-0415-092f-502f9f7e3e07.png)

作成したpowershellプログラムはモジュールファイルとして保存します。
毎回わざわざインポートしなくても済むように、既定のフォルダ（win7以降x64環境なら%Programfiles%\WindowsPowershell\Modules）配下に作成した関数名と同じフォルダを作り、同じファイル名で保存します。




##3.2．SQL実行結果で色々と遊ぶ

前項で作成したコマンドレッドを使って以下の様にSQL実行結果を変数に保存して使いまわすことが出来ます。

```powershell
$data = Execute-SymfoSQL -sql "SELECT * FROM 会社表"
```

変数に保持したオブジェクトはSystem.Data.Datasetクラスとなっており、コマンドレッド関数内で指定したtestTableというインデックスでSystem.Data.DataTableクラスのテーブルにアクセスできます。

```powershell
$data[1].Tables["testTable"]

会社番号 会社名 電話番号       住所
-------- ------ --------       ----
       1 夢幻   +81312345678   東京湾
       2 寿限無 +81322345678   東京湾２丁目
       3 バブル +81332345678   東京湾３丁目
```

勿論インデックス番号でもアクセスでき、DataTableクラスメンバの利用も可能です。以下はSelectメソッドで会社番号が1であるデータを抽出しています。

```powershell
$data[1].Tables[0].Select("会社番号=1")

会社番号 会社名 電話番号       住所
-------- ------ --------       ----
       1 夢幻   +81312345678   東京湾
```

以下は行としてテーブルの1行目を取り出しています。（実行結果は上と同じ）

```powershell
$data[1].Tables[0].Rows[0]

会社番号 会社名 電話番号       住所
-------- ------ --------       ----
       1 夢幻   +81312345678   東京湾
```

また、Javaでいうところのリフレクションで生成したオブジェクト同様にメンバが生成されデータが格納されるため、以下の様に直感的にデータアクセスする事も可能です。

```powershell
$data[1].Tables["testTable"].Select("会社番号=1").電話番号
+81312345678
```

---

#4．さいごに
　作成した環境は当然職場のPCなので、このブログ書くのに評価版を私用ノートに構築する方が時間がかかったぞ…_(:3 」∠ )_
　60日無料で使える評価版は[富士通HPのここ](http://software.fujitsu.com/cgi-bin/mksearch.cgi?fmt=%2Fjp%2Fmiddleware%2Fdownload%2Fproduct&itype=download&icell005=Symfoware)からダウンロードできます。（無料登録が必要）