AutoRESTを有効化したJSON Relational Dualityビューに対してPythonからGET/PUTを行う

# はじめに

この記事は、こちらの2つの記事の続きになります。

https://qiita.com/500InternalServerError/items/e0ced3dfc8d958f03059

https://qiita.com/500InternalServerError/items/d6d24e201c32ccf69a96

JSON-to-Dualityマイグレータを使用して、JSONドキュメント・セットからJSON Relational Dualityビューの作成およびJSONドキュメントのインポートを行い、ORDSをインストールして、スキーマに対してAutoRESTを有効にした状態を前提としています。

:::note warn
注意
こちらの記事の内容はあくまで個人の実験メモ的な内容のため、こちらの内容を利用した場合のトラブルには一切責任を負いません。
また、こちらの記事の内容を元にしたOracleサポートへの問い合わせはご遠慮ください。
:::

# 1.事前確認

SQL*Plusからtestuserユーザとして、PDBに接続します。
```
[oracle@basedb23ai ~]$ sqlplus testuser/Demo#1Demo#1@db23aihp_pdb1

SQL*Plus: Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on Mon Apr 7 08:57:37 2025
Version 23.7.0.25.01

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

Last Successful login time: Mon Apr 07 2025 08:49:37 +09:00

Connected to:
Oracle Database 23ai EE High Perf Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems
Version 23.7.0.25.01

SQL> 
```

JSON Relational Dualityビューcourseに対して、AutoRESTを有効にします。
```sql
SQL> BEGIN
  2      ORDS.ENABLE_OBJECT(
  3          p_enabled      => TRUE,
  4          p_schema       => 'TESTUSER',
  5          p_object       => 'COURSE',
  6          p_object_type  => 'VIEW',
  7          p_object_alias => 'course'
  8      );
  9      COMMIT;
 10  END;
 11  /

PL/SQL procedure successfully completed.

SQL>
```

JSON Relational Dualityビューcourse内の_idがMATH103のドキュメントの内容を確認します。
```sql
SQL> set pagesize 100
SQL> SELECT JSON_SERIALIZE(data PRETTY) FROM course c
  2  WHERE c.data."_id" = 'MATH103';

JSON_SERIALIZE(DATAPRETTY)
----------------------------------------------------------------------------------
{
  "_id" : "MATH103",
  "_metadata" :
  {
    "etag" : "5EA16B170A05B2D151DCA39A7315375B",
    "asof" : "00000000004DF301"
  },
  "name" : "Advanced Algebra",
  "Notes" : null,
  "teacher" :
  {
    "name" : "Colin J.",
    "teacherId" : 103
  },
  "students" :
  [
    {
      "name" : "Francis K.",
      "studentId" : 3
    },
    {
      "name" : "Georgia D.",
      "studentId" : 4
    },
    {
      "name" : "Ileana D.",
      "studentId" : 6
    },
    {
      "name" : "Katie H.",
      "studentId" : 8
    },
    {
      "name" : "Luis F.",
      "studentId" : 9
    }
  ],
  "creditHours" : 3,
  "courseId" : "MATH103"
}


SQL> 
```
Notesの値がNullであることが確認できました。

JSON Relational Dualityビューcourseのベースとなる表course_rootの内容を確認します。
```sql
SQL> col name for a20
SQL> col notes for a35
SQL> col course_id for a10
SQL> set linesize 120
SQL> SELECT * FROM course_root;

NAME		         NOTES				                 COURSE_ID  CREDIT_HOURS TEACHER_ID_COURSE_TEACHER
-------------------- ----------------------------------- ---------- ------------ -------------------------
Algebra 	         Prerequisite for Advanced Algebra	 MATH101	           3		               101
Calculus						                         MATH102	           4		               101
Algorithms						                         CS101		           5		               102
Data Structures 					                     CS102		           3		               102
Advanced Algebra					                     MATH103	           3		               103

SQL>
```
course_idがMATH103の行のnotes列の値がNULLであることが確認できました。

SQL*Plusを終了します。
```
SQL> exit
Disconnected from Oracle Database 23ai EE High Perf Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems
Version 23.7.0.25.01
[oracle@basedb23ai ~]$
```

# 2. PythonからのGET/PUT操作

Pythonを起動します。
```
[opc@db23ai ~]$ python
Python 3.9.20 (main, Oct 24 2024, 07:04:44) 
[GCC 8.5.0 20210514 (Red Hat 8.5.0-22.0.1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 
```

必要なモジュールをインポートします。
```python
>>> import requests
>>> import pprint
>>> import json
```

RESTエンドポイントを設定します。
```python
>>> id = 'MATH103'
>>> url = 'http://localhost:8080/ords/testuser/course/' + id
```

RESTエンドポイントに対して、GETリクエストを実行します。
```python
>>> resp_get = requests.get(url)
```

GETリクエストのレスポンスを表示します。
```python
>>> json_data = resp_get.json()
>>> pprint.pprint(json_data, indent=4)
{   'Notes': None,
    '_id': 'MATH103',
    '_metadata': {   'asof': '00000000004DF8DF',
                     'etag': '5EA16B170A05B2D151DCA39A7315375B'},
    'creditHours': 3,
    'links': [   {   'href': 'http://localhost:8080/ords/testuser/course/MATH103',
                     'rel': 'self'},
                 {   'href': 'http://localhost:8080/ords/testuser/metadata-catalog/course/item',
                     'rel': 'describedby'},
                 {   'href': 'http://localhost:8080/ords/testuser/course/',
                     'rel': 'collection'}],
    'name': 'Advanced Algebra',
    'students': [   {'name': 'Francis K.', 'studentId': 3},
                    {'name': 'Georgia D.', 'studentId': 4},
                    {'name': 'Ileana D.', 'studentId': 6},
                    {'name': 'Katie H.', 'studentId': 8},
                    {'name': 'Luis F.', 'studentId': 9}],
    'teacher': {'name': 'Colin J.', 'teacherId': 103}}
```

GETリクエストで取得したJSONドキュメントのNotesを「Very Difficult」に変更します。
```python
>>> json_data['Notes'] = "Very Difficult" 
```

変更後のJSONドキュメントを確認します。
```python
>>> pprint.pprint(json_data, indent=4)
{   'Notes': 'Very Difficult',
    '_id': 'MATH103',
    '_metadata': {   'asof': '00000000004DF8DF',
                     'etag': '5EA16B170A05B2D151DCA39A7315375B'},
    'creditHours': 3,
    'links': [   {   'href': 'http://localhost:8080/ords/testuser/course/MATH103',
                     'rel': 'self'},
                 {   'href': 'http://localhost:8080/ords/testuser/metadata-catalog/course/item',
                     'rel': 'describedby'},
                 {   'href': 'http://localhost:8080/ords/testuser/course/',
                     'rel': 'collection'}],
    'name': 'Advanced Algebra',
    'students': [   {'name': 'Francis K.', 'studentId': 3},
                    {'name': 'Georgia D.', 'studentId': 4},
                    {'name': 'Ileana D.', 'studentId': 6},
                    {'name': 'Katie H.', 'studentId': 8},
                    {'name': 'Luis F.', 'studentId': 9}],
    'teacher': {'name': 'Colin J.', 'teacherId': 103}}
```

PUTリクエストのためのヘッダー情報をセットします。
```python
>>> headers = {'content-type':'application/json'}
```

変更後のJSONドキュメントをPUTリクエストでRESTエンドポイントに送信します。
```python
>>> resp_put = requests.put(url, json=json_data, headers=headers)
```

PUTリクエストのレスポンス・コードを確認します。
```python
>>> print('Response code received: {code} '.format(code=resp_put.status_code))
Response code received: 200 
>>>
```
レスポンス・コードが200なので、処理が成功したことがわかりました。

RESTエンドポイントに対して、再度GETリクエストを送信し、JSONドキュメントを取得します。

```python
>>> resp_get_new = requests.get(url)
```

GETリクエストのレスポンスを表示します。
```python
>>> json_data_new = resp_get_new.json()
>>> pprint.pprint(json_data_new, indent=4)
{   'Notes': 'Very Difficult',
    '_id': 'MATH103',
    '_metadata': {   'asof': '00000000004DF8E5',
                     'etag': '3ACE9FE556F242391CEE6FE183C5155D'},
    'creditHours': 3,
    'links': [   {   'href': 'http://localhost:8080/ords/testuser/course/MATH103',
                     'rel': 'self'},
                 {   'href': 'http://localhost:8080/ords/testuser/metadata-catalog/course/item',
                     'rel': 'describedby'},
                 {   'href': 'http://localhost:8080/ords/testuser/course/',
                     'rel': 'collection'}],
    'name': 'Advanced Algebra',
    'students': [   {'name': 'Francis K.', 'studentId': 3},
                    {'name': 'Georgia D.', 'studentId': 4},
                    {'name': 'Ileana D.', 'studentId': 6},
                    {'name': 'Katie H.', 'studentId': 8},
                    {'name': 'Luis F.', 'studentId': 9}],
    'teacher': {'name': 'Colin J.', 'teacherId': 103}}
>>>
```

_idがMATH103のドキュメントが更新されていることが確認できました。

# 3. SQL*Plusからデータを確認する

SQL*Plusからtestuserユーザとして、PDBに接続します。
```
[oracle@basedb23ai ~]$ sqlplus testuser/Demo#1Demo#1@db23aihp_pdb1

SQL*Plus: Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on Mon Apr 7 08:57:37 2025
Version 23.7.0.25.01

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

Last Successful login time: Mon Apr 07 2025 09:00:37 +09:00

Connected to:
Oracle Database 23ai EE High Perf Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems
Version 23.7.0.25.01

SQL> 
```

JSON Relational Dualityビューcourse内の_idがMATH103のドキュメントの内容を確認します。
```sql
SQL> SELECT JSON_SERIALIZE(data PRETTY) FROM course c
  2  WHERE c.data.courseId = 'MATH103';

JSON_SERIALIZE(DATAPRETTY)
------------------------------------------------------------------------------------------------------------------------
{
  "_id" : "MATH103",
  "_metadata" :
  {
    "etag" : "3ACE9FE556F242391CEE6FE183C5155D",
    "asof" : "00000000004DF99D"
  },
  "name" : "Advanced Algebra",
  "Notes" : "Very Difficult",
  "teacher" :
  {
    "name" : "Colin J.",
    "teacherId" : 103
  },
  "students" :
  [
    {
      "name" : "Francis K.",
      "studentId" : 3
    },
    {
      "name" : "Georgia D.",
      "studentId" : 4
    },
    {
      "name" : "Ileana D.",
      "studentId" : 6
    },
    {
      "name" : "Katie H.",
      "studentId" : 8
    },
    {
      "name" : "Luis F.",
      "studentId" : 9
    }
  ],
  "creditHours" : 3,
  "courseId" : "MATH103"
}


SQL>
```
_idがMATH103のドキュメントのNotesが「Very Difficult」に更新されていることが確認できました。。


JSON Relational Dualityビューcourseのベースとなる表course_rootの内容を確認します。
```sql
SQL> col name for a20
SQL> col notes for a35
SQL> col course_id for a10
SQL> set linesize 120
SQL> SELECT * FROM course_root;

NAME		         NOTES				                 COURSE_ID  CREDIT_HOURS TEACHER_ID_COURSE_TEACHER
-------------------- ----------------------------------- ---------- ------------ -------------------------
Algebra 	         Prerequisite for Advanced Algebra	 MATH101	           3		               101
Calculus						                         MATH102	           4		               101
Algorithms						                         CS101		           5		               102
Data Structures 					                     CS102		           3		               102
Advanced Algebra     Very Difficult			             MATH103	           3		               103

SQL> 
```
course_idがMATH103の行のnotes列の値が「Very Difficult」に更新されていることが確認できました。