Oracle CloudにあるAutonomous Data WarehouseにPythonから接続してみる（cx_Oracleの利用）

# はじめに

※「cx_Oracleは分かる、ADW固有の情報が知りたい」方は、途中スキップして「[ADW環境への接続](https://qiita.com/mikika/items/17e6949b21fcc447ee98#adw%E7%92%B0%E5%A2%83%E3%81%B8%E3%81%AE%E6%8E%A5%E7%B6%9A)」から参照ください。

cx_OracleはPythonからOracle Databaseに接続するためのモジュールです。
Pythonプログラムを実行するクライアント側にインストールして利用します。

Oracle Autonomous Data Warehouse（ADW）はOracle Cloud Infrastructure（OCI）環境にあるAutonomousで超高速なデータベースですが、これもOracle Databaseなので、cx_Oracleで接続できます。

具体的には

- Oracle Client (Instant Client でも Full Clientでも良いが、今回は前者を利用）
- cx_Oracle

の２つをインストールします。

# 環境

- Ubuntu 
- Python 3.6.7

# インストール

公式ドキュメントの英語版・日本語版

- [Using Oracle Autonomous Data Warehouse - Connect with Python, Node.js, and other Scripting Languages](https://docs.oracle.com/en/cloud/paas/autonomous-data-warehouse-cloud/user/connecting-nodejs.html#GUID-AB1E323A-65B9-47C4-840B-EC3453F3AD53)
- [Oracle Autonomous Data Warehouseの使用 - Python、Node.js、およびその他のスクリプト言語での接続](
https://docs.oracle.com/cd/E83857_01/paas/autonomous-data-warehouse-cloud/user/connecting-nodejs.html#GUID-AB1E323A-65B9-47C4-840B-EC3453F3AD53)


に従って実施。以下やったこと。

## Instant Client のインストール

今回は 自分の $HOME以下にインストールすることにする。

[OTNダウンロードサイト：Oracle Instant Client](
https://www.oracle.com/technetwork/database/database-technologies/instant-client/overview/index.html)　より、
Version 18.3.0.0.0, Base - Basic Package の
 instantclient-basic-linux.x64-18.3.0.0.0dbru.zip
をダウンロード。

$HOME直下にダウンロードしたファイルを配置し、unzip。

```
$ unzip instantclient-basic-linux.x64-18.3.0.0.0dbru.zip
```

展開後、中身を確認。

```
$ cd $HOME/instantclient_18_3
$ ls -la
total 227288
drwxrwxrwx 1 app app       512 Feb 13 22:25 .
drwxr-xr-x 1 app app       512 Feb 13 23:18 ..
-rw-r--r-- 1 app app      1317 Jun 28  2018 BASIC_README
-rwxr-xr-x 1 app app     40617 Jun 28  2018 adrci
-rwxr-xr-x 1 app app     57556 Jun 28  2018 genezi
lrwxrwxrwx 1 app app        17 Feb 13 22:18 libclntsh.so -> libclntsh.so.18.1 ★★★
..(略)..
```

★★★は、インストール手順によると、無ければシンボリックリンクを作成せよとのことだったが、既に存在していたので特に何もしない。

### LD_LIBRARY_PATHの設定

$HOME/.bash_profile に追加

```:.bash_profile
export LD_LIBRARY_PATH=/mnt/c/linux_home/instantclient_18_3:$LD_LIBRARY_PATH
```

## cx_Oracleのインストール

https://cx-oracle.readthedocs.io/en/latest/installation.html

に従って行う。

```
$ pip install cx_Oracle
Collecting cx_Oracle
  Downloading https://files.pythonhosted.org/packages/9f/87/3f133ffdca70547aa33a1c4b4990e70c605f0668250426edfa847af0f54d/cx_Oracle-7.0.0-cp36-cp36m-manylinux1_x86_64.whl (675kB)
    100% |████████████████████████████████| 675kB 2.4MB/s
Installing collected packages: cx-Oracle
Successfully installed cx-Oracle-7.0.0
$
```

### libaioのインストール

手順の中ではInstant Clientのインストール欄に書かれていたが、libaio(環境によっては libaio1 と呼ばれるもの)をインストール

```
$ sudo apt-get install libaio1
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following package was automatically installed and is no longer required:
  libfreetype6
Use 'sudo apt autoremove' to remove it.
The following NEW packages will be installed:
  libaio1
0 upgraded, 1 newly installed, 0 to remove and 124 not upgraded.
Need to get 6448 B of archives.
After this operation, 30.7 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu bionic/main amd64 libaio1 amd64 0.3.110-5 [6448 B]
Fetched 6448 B in 1s (4996 B/s)
Selecting previously unselected package libaio1:amd64.
(Reading database ... 35007 files and directories currently installed.)
Preparing to unpack .../libaio1_0.3.110-5_amd64.deb ...
Unpacking libaio1:amd64 (0.3.110-5) ...
Processing triggers for libc-bin (2.27-3ubuntu1) ...
Setting up libaio1:amd64 (0.3.110-5) ...
Processing triggers for libc-bin (2.27-3ubuntu1) ...
$
```

# インストールできたことを確認

Instant Client と cx_Oracleがインストールできたことを確認

```
$ python
Python 3.6.7 (default, Oct 22 2018, 11:32:17)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cx_Oracle
>>> cx_Oracle.clientversion()
(18, 3, 0, 0, 0)
>>>
```

# ADW環境への接続

## cx_Oracle 詳しい方へ：ざっくり説明

ADWに特化した情報としては、

- 接続に必要なクライアント資格証明ファイル一式（Wallet_XXX.zip）が必要で、Oracle Clientの network/admin 配下に置き展開
- *.zip内に tnsnames.ora も含むので、pythonからは dsn= で、tnsnames.ora のエントリ（ネット・サービス名）を指定
- ※ ADWではインスタンス作成時に3つの事前定義されたネット・サービス名が作られる( XXX_high, _medium, _low ) ので、通常はそのどれかを指定すればよい

## 準備

以下の情報やファイルを準備する

- 接続するためのWallet_XXX.zip（クライアント・セキュリティ資格証明のファイル一式 ）①
- 接続に使用する、ネット・サービス名（tnsnames.oraのエントリのこと）②
- 接続するデータベースユーザの名前・パスワード ③

②は、通常は、\<作成したADWの名前\>\_high, \_medium, \_low のうちどれか。

①は、[Download Client Credentials (Wallets)](https://docs.oracle.com/en/cloud/paas/autonomous-data-warehouse-cloud/user/connect-download-wallet.html#GUID-B06202D2-0597-41AA-9481-3B174F75D4B1) の手順でダウンロードする。

## 接続に必要なセキュリティ資格証明を設定

ここでは、ADWを myadw という名前で作成したとし

- ① Wallet_myadw.zip 
- ② myadw_high
- ③ usename=scott, password=tiger

とする。①を instantclient_18_3/network/admin の下に配置し、展開。

```
$ cp Wallet_myadw.zip $HOME/instantclient_18_3/network/admin/Wallet_myadw.zip
$ cd $HOME/instantclient_18_3/network/admin
$ unzip Wallet_myadw.zip
```

厳密にはzipファイル中の一部のファイル（tnsnames.ora、sqlnet.ora、cwallet.sso、ewallet.p12）が必要。管理者から必要なファイルだけ受け取っている場合は、それらのファイルを instantclient_18_3/network/admin/ 配下に置く。

## ADWに接続しSQLを実行

cx_Oracle.connect()に、接続情報を指定する。
dsn=にtnsnames.oraのエントリ（②）を指定。

```conn_adw.py
import cx_Oracle
conn=cx_Oracle.connect(user='scott',password='tiger',dsn='myadw_high')

sql='select table_name, status from user_tables'
print(sql)
cur = conn.cursor()
for row in cur.execute(sql):
    print(row)
```

実行すると 上の sql='select table_name, status from user_tables' 結果が返る。

```
$ python conn_adw.py
select table_name, status from user_tables
('SMALL_TABLE', 'VALID')
('SUPPLEMENTARY_DEMOGRAPHICS2', 'VALID')
('CUSTOMERS360', 'VALID')
('CUSTOMERS360_SET', 'VALID')
...以下略...
```

# ついでに：SQL*Plusのインストール

[OTNダウンロードサイト：Oracle Instant Client](
https://www.oracle.com/technetwork/database/database-technologies/instant-client/overview/index.html) から、Instant Client の sqlplus をダウンロードしてunzip
（Toolsの欄にある）

```
$ unzip instantclient-sqlplus-linux.x64-18.3.0.0.0dbru.zip
Archive:  instantclient-sqlplus-linux.x64-18.3.0.0.0dbru.zip
  inflating: instantclient_18_3/glogin.sql
  inflating: instantclient_18_3/libsqlplusic.so
  inflating: instantclient_18_3/libsqlplus.so
  inflating: instantclient_18_3/sqlplus
  inflating: instantclient_18_3/SQLPLUS_README
$
```

環境変数の設定（既に通したLD_LIBRARY_PATHに加えて、PATHを通す）

```
$ cat .bash_profile
export LD_LIBRARY_PATH=/mnt/c/linux_home/instantclient_18_3:$LD_LIBRARY_PATH
export PATH=/mnt/c/linux_home/instantclient_18_3:$PATH
$ . .bash_profile
```

SQL*Plusを起動

```
$ sqlplus /nolog

SQL*Plus: Release 18.0.0.0.0 - Production on Thu Jan 31 13:53:14 2019
Version 18.3.0.0.0

Copyright (c) 1982, 2018, Oracle.  All rights reserved.

SQL> exit
```