Autonomous Database : GCP Cloud Run Functionsの関数をSQLファンクションとして実行してみた

# はじめに
2025年最初のAutonomous Databaseの新機能として、GCP Cloud Run Functionsの関数をSQLファンクションとして実行できる機能が実装されたので、早速試してみました。

※こちらの内容はあくまで個人が検証した内容であり、他の環境で正しく動作することを保証するものではありません。また、こちらの記事を元にしたOracleサポートへの問い合わせはご遠慮ください。

# 1. Google サービス・アカウントの有効化
今回は、Autonomous DatabaeからCloud Run Functionsにアクセスする際にサービス・アカウントベースの認証を使用します。
まずはじめに、Autonomous DatabaseでGCPのサービス・アカウントによる認証を有効化します。

adminユーザとして、Autonomous Databaseに接続します。
```
[oracle@oracle23ai ~]$ sqlplus admin/Demo#1Demo#1@atp23ai

SQL*Plus: Release 23.0.0.0.0 - Production on Thu Jan 9 11:58:12 2025
Version 23.4.0.24.05

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

Last Successful login time: Tue Dec 24 2024 11:42:07 +09:00

Connected to:
Oracle Database 23ai Enterprise Edition Release 23.0.0.0.0 - Production
Version 23.6.0.24.11

SQL>
```
DBMS_CLOUD_ADMIN.ENABLE_PRINCIPAL_AUTHプロシージャを使用して、GCPのサービス・アカウントによる認証を有効化します。
```
SQL> EXEC DBMS_CLOUD_ADMIN.ENABLE_PRINCIPAL_AUTH( provider => 'GCP' );

PL/SQL procedure successfully completed.

SQL>
```
CLOUD_INTEGRATIONSビューを使用して、Autonomous Databaseのサービス・アカウントを確認します。
```
SQL> col param_name for a20
SQL> col param_value for a70
SQL> set linesize 100
SQL> SELECT * FROM CLOUD_INTEGRATIONS WHERE param_name = 'gcp_service_account';

PARAM_NAME	         PARAM_VALUE
-------------------- ----------------------------------------------------------------------
gcp_service_account  GCP-SA-46886-7138@gcp-pa-project1.iam.gserviceaccount.com


SQL>
```
PARAM_VALUEの値がAutonomous Databaseのサービス・アカウントです。
Google Cloudコンソールでの設定に使用しますので、メモしておきます。

# 2. IAMロールの作成とサービス・アカウントへのロールの割り当て

Google CloudコンソールでAutonomous Databasのサービス・アカウントに割り当てるIAMロールを作成します。
![スクリーンショット 2025-01-09 23.55.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/4a776ce8-fcd6-83b3-169d-ec0c4c87e288.png)

今回は「ADB-Functions-role」という名前のロールを作成し、Cloud Run Functionsの関数をSQLファンクションとして登録、実行するために必要な以下の4つの権限を付与しました。

・cloudfunctions.functions.invoke
・cloudfunctions.functions.list
・run.jobs.run
・run.routes.invoke 

![スクリーンショット 2025-01-10 0.00.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/a61e517e-ef4e-30e9-8eb2-3e1271cfc8f9.png)

ロールを作成したら、Autonomous Databaseのサービス・アカウントにロールを割り当てます。

![スクリーンショット 2025-01-09 23.47.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/86ab8fba-d170-34ce-1179-49630a53a7b5.png)

「新しいプリンシパル」に、1.で取得したAutonomous Databaseのサービス・アカウント（CLOUD_INTEGRATIONSビューのPARAM_VALUE列の値）を入力し、ロール「ADB-Functions-role」を割り当てて保存します。

![スクリーンショット 2025-01-10 0.04.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/09040e4d-315e-71a2-0d4a-7375cb9ba563.png)

Autonomous Databaseのサービス・アカウントへのロールの割り当てが完了しました。
![スクリーンショット 2025-01-09 23.51.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/07a36536-bf4b-09dc-1f92-0194785f98ff.png)

# 3. GCP Cloud Run Functionsの関数をSQLファンクションとして登録

GCPのプロジェクト内にはfunction1という関数が作成されています。
![スクリーンショット 2025-01-10 16.10.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/d27199dd-bb6c-5136-1a40-090f3327bed1.png)

こちらのfunction1は、「Hello from GCP!」という文字列を返す単純な関数です。
![スクリーンショット 2025-01-10 16.10.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/17761d88-e428-6a86-8866-84a02ff38923.png)

DBMS_CLOUD_FUNCTION.CREATE_CATALOGプロシージャを使用して、ファンクション・カタログを作成します。
ここではGCP_DEMO_CATALOGという名前のファンクション・カタログを作成します。

サービス・アカウントを使用した認証を使用する場合は、credential_nameに「GCP$PA」を指定します。
また、cloud_paramsには、"project_id"として、GCPのプロジェクトIDを指定します。
```
SQL> BEGIN
  2      DBMS_CLOUD_FUNCTION.CREATE_CATALOG (
  3          credential_name  => 'GCP$PA', 
  4          catalog_name     => 'GCP_DEMO_CATALOG', 
  5          service_provider => 'GCP',
  6          cloud_params     => '{"project_id":"xxxx-xxxx-123456"}'
  7      );
  8  END;
  9  /

PL/SQL procedure successfully completed.

SQL>
```
USER_CLOUD_FUNCTION_CATALOGビューで、ファンクション・カタログGCP_DEMO_CATALOGが作成されたことを確認します。
```
SQL> select * from USER_CLOUD_FUNCTION_CATALOG
  2  WHERE cloud_provider = '"GCP"';

CATALOG_NAME	     CLOUD_PROVIDER
-------------------- --------------------
GCP_DEMO_CATALOG     "GCP"

SQL>
```
USER_CLOUD_FUNCTIONビューで、ユーザが使用可能なクラウド・ファンクションがあるかを確認します。
```
SQL> select * from USER_CLOUD_FUNCTION;

no rows selected

SQL>
```
この時点では、またユーザが使用可能なクラウド・ファンクションはありません。

DBMS_CLOUD_FUNCTION.SYNC_FUNCTIONSプロシージャを使用して、ファンクション・カタログ内の関数のラッパーSQLファンクションを作成します。

```
SQL> EXEC DBMS_CLOUD_FUNCTION.SYNC_FUNCTIONS(catalog_name => 'GCP_DEMO_CATALOG');

PL/SQL procedure successfully completed.

SQL>
```
ラッパーSQLファンクションが作成されたか確認してみます。
```
SQL> SELECT catalog_name, function_name FROM USER_CLOUD_FUNCTION;

CATALOG_NAME	     FUNCTION_NAME
-------------------- --------------------
GCP_DEMO_CATALOG     FUNCTION1

SQL>
```
Cloud Run Functionsの関数function1のラッパーSQLファンクションFUNCTION1が作成されていることが確認できました。

# 4. GCP Cloud Run Functionsの関数のラッパーSQLファンクションの実行
ラッパーSQLファンクションFUNCTION1を実行してみます。
```
SQL> SELECT function1('{}') FROM dual;

FUNCTION1('{}')
--------------------------------------------------------------------------------
{"STATUS":"200","RESPONSE_BODY":"Hello from GCP!"}

SQL>
```
GCP Cloud Run Functionsの関数function1が実行され、レスポンスが正しく返ってきている事が確認できました。

# 参考情報
・[Steps to Invoke Google Cloud Run Functions as SQL Functions](https://docs.oracle.com/en/cloud/paas/autonomous-database/serverless/adbsb/user-defined-functions-gpc.html#GUID-56969307-8904-4D2E-BA68-CB7192329235)
・[Use Google Service Account to Access Google Cloud Platform Resources](https://docs.oracle.com/en/cloud/paas/autonomous-database/serverless/adbsb/google-service-account.html#GUID-DB8D0B97-7BC5-42C0-B556-3579D834D34B)