HANA Cloudのテーブルデータをファイルに出力する方法

## はじめに
HANA Cloudのテーブルデータをファイルに出力したい場合、一番簡単な方法は、Database Explorerでクエリを実行して結果をダウンロードすることでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/688173d8-840e-046c-7ac3-02a4d99cd9f2.png)

しかし、Database Explorerで抽出できるのはデフォルトで1000行までです。もっと大量のデータをダウンロードしたい場合はどうしたらよいでしょうか。この記事では、3つの方法を紹介します。

1. Database Exlorerの設定で最大表示行数を変更する
1. HANA Clientでローカルファイルに出力する
1. Cloud Integrationで出力する

## 方法1：Database Exlorerの設定で最大表示行数を変更する
以下のKBAに記載の通り、Database Explorerの設定で最大表示行数を1000より大きくすることができます。
[KBA 3131569 - How-To: Configure the maximum number of rows displayed in Result from HANA Database Explorer](https://me.sap.com/notes/0003131569)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/084ad187-2bce-bb01-3705-04ee189fd379.png)

ただし、ここにも制限があります。上記KBAに「**出力できる最大のサイズは16MB**」とあります。

## 方法2：HANA Clientでローカルファイルに出力する
以下のKBAに、16MBを超えた場合の対応が記載されています。hdbsqlコマンドを使って出力する方法です。
[2942727 - How-To: Export large select output to local file](https://me.sap.com/notes/2942727)

```
hdbsql -n <DB host name>:<SQL port> -u <username> -p <password> -x "<your select query>" > /<path>/output_file.txt
```

hdbsqlコマンドを使用するにはHANA Clientをインストールする必要があります。インストール方法は以下のチュートリアルに記載されています。

https://developers.sap.com/tutorials/hana-clients-install.html

HANA Cloud側では、接続する端末のIPアドレスを許可しておく必要があります（今回はトライアル環境のため全てのIPアドレスを許可）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/cc2f1f65-b0bb-baa9-2139-98e20846c473.png)

接続に必要な`<DB host name>:<SQL port>`の部分は、HANA Cloudのインスタンスのアクションから"Copy SQL Endpoint"でコピーできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/a31e16de-8aa1-f9f1-6efa-53266472aaca.png)

コマンド例
```
hdbsql -n 118869d7-da16-4d93-b1e2-42bd39ed12da.hana.trial-us10.hanacloud.ondemand.com:443 -u user -p password -x "select * from ""MY_USERS"".""User""" > test\users.txt
```

約42万件のデータが30秒以内にダウンロードできました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/51912a0c-eab7-074b-5afb-93f4885411bb.png)

以下が取得したデータです。
```
USERID,FIRSTNAME,LASTNAME,EMAIL,PHONENUMBER
1,"FirstName1","LastName1","email1@example.com","123456789"
2,"FirstName2","LastName2","email2@example.com","123456789"
3,"FirstName3","LastName3","email3@example.com","123456789"
```

## 方法3: Cloud Integrationで出力する
SFTPサーバなどに定期的に出力したい場合は、Cloud Integrationを使うことができます。ただし、Cloud Integrationに大量データを持ち込むことになり、課金に影響しますのでご注意ください。

**ステップ**
1. JDBC Materialを作成
1. フローを作成
1. 動作確認

### 3.1. JDBC Materialを作成
はじめにHANA Cloudへの接続を定義したJDBC Materialを作成しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/9dedcc1d-28b8-ed35-6ecc-58721d6f4bf6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/44fc73aa-5292-c821-89f5-8335ef6ea602.png)
以下を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/a5bace02-9517-b21a-05a0-987bc3c6fb8c.png)

|項目  |設定値  |
|---|---|
|Name  |任意  |
|Database TYpe  |SAP HANA Cloud  |
|Database  |データベースのユーザ  |
|Password  |上記ユーザのパスワード  |
|JDBC URL  |jdbs:sap:// + <2.で確認したSQL Endpoint>  |

JDBC URLの例：`jdbc:sap://118869d7-da16-4d93-b1e2-42bd39ed12da.hana.trial-us10.hanacloud.ondemand.com:443`

### 3.2. フローを作成
以下が作成したフローです。HANA Cloudに接続してテーブルデータ（約42万件）を全件取得し、ログに添付するという内容です。デプロイ時に一度だけ起動するようにタイマーを設定しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/23bced1a-f20d-2177-7cca-381067cc90e5.png)
最初のステップでは、Content ModifierによりHANA Cloudに渡すクエリを設定します。SQLをそのまま書くことができます。（または、[ヘルプ](https://help.sap.com/docs/cloud-integration/sap-cloud-integration/payload-and-operation)にあるようにXMLで指定することも可能です）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/6d3829dd-fb42-08fb-5576-8026ffa0c5b7.png)

次のステップでは、JDBC Receiver AdapterによりHANA Cloudに接続してクエリを実行します。**JDBC Data Source Alias**にあらかじめ作成しておいたJDBC Materialの名前を設定します。**Maximum Records**は想定される取得件数より大きくなるように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/1b9914c3-c328-6615-1402-3455a67249f4.png)
HANA Cloudからは以下のような形式でレスポンスが返ってきます。
```xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ROOT>
	<select_response>
		<row>
			<USERID>1</USERID>
			<FIRSTNAME>FirstName1</FIRSTNAME>
			<LASTNAME>LastName1</LASTNAME>
			<EMAIL>email1@example.com</EMAIL>
			<PHONENUMBER>123456789</PHONENUMBER>
		</row>
		<row>
			<USERID>2</USERID>
			<FIRSTNAME>FirstName2</FIRSTNAME>
			<LASTNAME>LastName2</LASTNAME>
			<EMAIL>email2@example.com</EMAIL>
			<PHONENUMBER>123456789</PHONENUMBER>
		</row>
	</select_response>
</ROOT>
```
次のステップでは、XML Modifierでレスポンスの先頭のxmlタグを取り除きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/ab7a9289-cb9a-6adc-e91b-8a80cc5265fc.png)
次のステップでは、XMLをCSVに変換します。**Path to Source Element in XSD**に`/ROOT/select_response/row`を指定します。また、ヘッダ付きで出力したいので**Include Field Name as Headers**にチェックを付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/0a2e61f3-29ee-35c0-2eff-ffbb4f7c9352.png)

最後のステップで、Groovy ScriptによりCSVに変換したコンテンツをログに添付します。
```groovy
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
def Message processData(Message message) {
    def body = message.getBody(java.lang.String) as String;
    def messageLog = messageLogFactory.getMessageLog(message);
    if(messageLog != null){
        messageLog.setStringProperty("Logging#1", "Printing Payload As Attachment")
        messageLog.addAttachmentAsString("Retrieved Data:", body, "text/plain");
     }
    return message;
}
```
### 3.3. 動作確認
デプロイするとフローが動き、取得したデータが添付文書に保存されます。実行時間は11秒ほどでした。中で色々な処理を行っているにも関わらず、HANA Clientよりも高速でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/f24d25e8-4afb-43a7-6a5e-9fe756c2c791.png)
以下が取得したデータです。HANA Clientで取得したときは文字列がダブルクォートで囲まれていましたが、こちらは囲まれていません。
```
USERID,FIRSTNAME,LASTNAME,EMAIL,PHONENUMBER
1,FirstName1,LastName1,email1@example.com,123456789
2,FirstName2,LastName2,email2@example.com,123456789
3,FirstName3,LastName3,email3@example.com,123456789
4,FirstName4,LastName4,email4@example.com,123456789
```