2025年3月29日土曜日

Playwright MCPを使ってOracle APEXのアプリケーションを操作する

前回の記事「MicrosoftのPlaywrightを使ってAPEXアプリケーションのE2Eテストを行う」で作成したAPEXアプリケーションを、Microsoftから公開されているPlaywright MCPを使ってClaude Desktopアプリケーションより操作してみます。

Playwright MCPを組み込んだClaude Desktopに、以下のメッセージを送信しています。
  1. http://localhost:8181/ords/r/apexdev/demonstration-emp-dept/dashboardを開いて
  2. ユーザー名とパスワードは自分で入力します。
  3. サインインできました。
  4. Employeesの一覧を開いて
  5. SCOTTのSalaryを3000から4000に変更して
  6. いえ、これでいいです。ありがとう!

巷ですごいと噂になっていましたが、本当にすごい。

この作業を実施するにあたって行なったことは、Playwright MCPサーバーをClaude Desktopに組み込んだだけです。

Claude Desktopの設定から開発者タブを開き、設定の編集をクリックします。


claude_desktopo_config.jsonが参照されるのでエディタでそのファイルを開き、GitHubのPlaywright MCPのページに書いてある設定を追加します。



変更を保存し、Claude Desktopを再起動したらPlaywright MCPの組み込みは完了です。

特に何もせずAPEXアプリケーションのページの構造が理解できるのは、Oracle APEXがデフォルトでアクセシビリティを考慮したHTMLを生成しているからなのか、Claude 3.7 Sonnetがすごいのか、どちらかはわかりません。

今回の記事は以上になります。

MicrosoftのPlaywrightを使ってAPEXアプリケーションのE2Eテストを行う

Microsoftから公開されているオープンソースのE2Eテスト自動化フレームワークのPlaywrightを使って、APEXアプリケーションのE2Eテストを実施してみます。

最終的には以下の作業を行います。作業環境には、macOSのpodmanでコンテナとして動作しているOracle APEXの環境を使っています。コード内の定数BASE_URLを変更することで、テスト対象とするアプリケーションは変えられます。PlaywrightのテストはPlaywrightをインストールした上で、VSCodeの拡張機能Playwright Test for VSCodeから実行しています。


以下より、作業について説明します。

最初にE2Eテストの対象とするAPEXアプリケーションを作成します。

サンプル・アプリケーションサンプル・データセットEMP/DEPTをインストールして、APEXアプリケーションを作成します。言語英語にします。テスト・コードではページのタイトルを参照しているため、言語を日本語にすると、確認のために指定している文字列も日本語にする必要があります。

SQLワークショップサンプル・データセットを開きます。

データ・セットEMP/DEPTインストール(すでにインストール済みであれば更新)をクリックします。


インストールする言語の指定を求められます。言語として英語を選択します。


すでに英語でインストール済みであれば、新規言語は選択しません(- 新しい言語の選択 -から変更しません)。

へ進みます。


新規であればデータセットのインストールをクリックします。


更新であれば既存のデータセットのリフレッシュをクリックします。


サンプル・データセットのロードが完了すると、そのデータを元にしたアプリケーションを作ることができます。

アプリケーションの作成をクリックします。


アプリケーション作成ウィザードが開きます。ダッシュボードファセット検索のページが追加済みです。テスト用のアプリケーションに沢山のページは不要なので、機能についてはすべてチェックを外します。

以上でアプリケーションの作成をクリックします。


アプリケーションが作成されます。


アプリケーションを実行し、今回のE2Eテストで行う操作を確認します。

アプリケーションにアクセスし、表示されるログイン・ページにて、以下の操作を行います。
  1. ユーザー名を入力する。
  2. パスワードを入力する。
  3. サインインをクリックする。

サインインが完了すると、ホーム・ページが開きます。

ホーム・ページ上で以下の操作を行います。
  1. Dashboardのカードをクリックし、Dashboardのページが開くことを確認します。
  2. Employeesのカードをクリックし、Employeesのファセット検索のページが開くことを確認します。
  3. Departmentsのカードをクリックし、Departmentsの対話モード・レポートのページが開くことを確認します。

Playwrightではセレクタを使って、操作する要素を特定します。

ログイン画面ではテキスト・フィールドにユーザー名とパスワードを入力し、ボタンのサインインをクリックしています。そのため、これらのテキスト・フィールドとボタンを特定するセレクタが必要です。

どのようなセレクタが適当か確認するために開発ツールの検証を呼び出し、それぞれの要素のHTMLを確認します。


タイプがテキスト・フィールドの場合は、以下のようなHTMLが生成されていました。
<input type="text" id="P9999_USERNAME" name="P9999_USERNAME" placeholder="ユーザー名" class="text_field apex-item-text apex-item-has-icon" autocomplete="username" value="admin" size="40" maxlength="100" data-enter-submit="false" data-is-page-item-type="true">
ページ・アイテムの名前がid属性として設定されているため、セレクタとしては#ページアイテム名、つまり#P9999_USERNAMEで特定できます。パスワードも同様に#P9999_PASSWORDで特定できます。

ボタンサインインについては、BUTTON要素を特定できる適当な属性がありません。
<button class="t-Button t-Button--hot lto18565948643221472_0" type="button" id="B18565948643221472" data-otel-label="LOGIN"><span class="t-Button-label">サインイン</span></button>
そのため、ボタンに静的IDとしてLOGIN設定します。


ボタンに設定した静的IDは属性idに設定されます。そのため、このボタンをセレクタ#LOGINで特定できます。
<button class="t-Button t-Button--hot lto18565948643221472_0" type="button" id="LOGIN" data-otel-label="LOGIN"><span class="t-Button-label">サインイン</span></button>
ホーム・ページのカードについても確認します。

カードに紐ずくA要素を特定するセレクタとして使える、これといった属性がありません。


<a href="/ords/r/apexdev/demonstration-emp-dept106/dashboard?session=8435741618687" class="t-Card-wrap" data-otel-label="">
      <div class="t-Card-icon u-color "><span class="t-Icon fa fa-dashboard"><span class="t-Card-initials" role="presentation"></span></span></div>
      <div class="t-Card-titleWrap">
        <h3 class="t-Card-title">Dashboard</h3>
        <h4 class="t-Card-subtitle"></h4>
      </div>
      <div class="t-Card-body">
        <div class="t-Card-desc"></div>
        <div class="t-Card-info"></div>
      </div>
      <span class="t-Card-colorFill u-color " aria-hidden="true"></span>
    </a>
ページの設定を確認します。

ページ・ナビゲーションのリージョンのタイプリストです。


左ペインでページ共有コンポーネントを開き、リストに適用されているテンプレートを見つけ(テンプレートCardsが適用されています)、コンポーネントの編集をクリックします。

このリージョンが参照しているHTMLのテンプレートが表示されます。


リスト・テンプレートCardsテンプレート定義を確認します。

A要素はテンプレート定義カレント・リスト・テンプレートおよび非カレント・リスト・テンプレートで、以下のように記述されています。
<a href="#LINK#" class="t-Card-wrap" #A05# data-otel-label="#A10#">

置換文字列#A05#に、セレクタとして利用可能な属性を設定することにします。

置換文字列#A05#に設定する文字列は、Dashboardのカードにid="menu-dashboard"Employeesid="menu-employees"Departmentsにはid="menu-departments"とします。

ページ・ナビゲーションのソースを確認します。

ソースとなるリストページ・ナビゲーションです。


リストのソースは共有コンポーネントとして作成されています。

共有コンポーネントリストを開きます。


リストの一覧にページ・ナビゲーションがあります。名前のリンクをクリックして、ページ・ナビゲーションを開きます。


リスト・エントリとしてDashboardEmployeesDepartmentsが含まれています。

最初にDashboardを開いて、属性を追加します。


テンプレート定義に含まれる置換文字列#A01#から#A10#は、ユーザー定義属性です。セクションのユーザー定義属性に移動し、置換文字列#A05#に対応している5. Link Attributesとしてid="menu-dashboard"を設定します。

変更の適用をクリックします。


同様にリスト・エントリEmployeesを開き、ユーザー定義属性5. Link Attributesとしてid="menu-employees"を設定します。


リスト・エントリDepartments5. Link Attributesid="menu-departments"を設定します。


以上で、Playwrightを使ってE2Eテストを行うために必要な、APEXアプリケーションの改変は完了です。

続いてPlaywrightをインストールします。PlaywrightのGetting StartedのInstallationの記述に従って、作業を行います。


いくつか方法がありますが、今回はnpmでインストールしました。

今回のE2Eテストを作成するディレクトリを作成します。本作業ではPlaywrightとしました。

mkdir Playwright

% mkdir Playwright

% 


作成したディレクトリに移動し、Playwrightをインストールします。

cd Playwright
npm init playwright@latest

プロジェクトの初期化に当たって、いくつか質問されます。今回はすべてデフォルトの設定で初期化しています。デフォルトではテスト・スクリプトの記述はTypeScriptで行い、テスト・スクリプトはサブフォルダのtestsに保存されます。

% cd Playwright

Playwright % npm init playwright@latest


> npx

> create-playwright


Getting started with writing end-to-end tests with Playwright:

Initializing project in '.'

Do you want to use TypeScript or JavaScript? · TypeScript

Where to put your end-to-end tests? · tests

Add a GitHub Actions workflow? (y/N) · false

Install Playwright browsers (can be done manually via 'npx playwright install')? (Y/n) · true

Initializing NPM project (npm init -y)…

Wrote to /Users/ynakakoshi/Documents/Playwright/package.json:


{

  "name": "playwright",

  "version": "1.0.0",

  "main": "index.js",

  "scripts": {

    "test": "echo \"Error: no test specified\" && exit 1"

  },

  "keywords": [],

  "author": "",

  "license": "ISC",

  "description": ""

}




Installing Playwright Test (npm install --save-dev @playwright/test)…


added 3 packages, and audited 4 packages in 1s


found 0 vulnerabilities

Installing Types (npm install --save-dev @types/node)…


added 3 packages, and audited 7 packages in 640ms


found 0 vulnerabilities

Writing playwright.config.ts.

Writing tests/example.spec.ts.

Writing tests-examples/demo-todo-app.spec.ts.

Writing package.json.

Downloading browsers (npx playwright install)…

✔ Success! Created a Playwright Test project at /Users/ynakakoshi/Documents/Playwright


Inside that directory, you can run several commands:


  npx playwright test

    Runs the end-to-end tests.


  npx playwright test --ui

    Starts the interactive UI mode.


  npx playwright test --project=chromium

    Runs the tests only on Desktop Chrome.


  npx playwright test example

    Runs the tests in a specific file.


  npx playwright test --debug

    Runs the tests in debug mode.


  npx playwright codegen

    Auto generate tests with Codegen.


We suggest that you begin by typing:


    npx playwright test


And check out the following files:

  - ./tests/example.spec.ts - Example end-to-end test

  - ./tests-examples/demo-todo-app.spec.ts - Demo Todo App end-to-end tests

  - ./playwright.config.ts - Playwright Test configuration


Visit https://playwright.dev/docs/intro for more information. ✨


Happy hacking! 🎭

 Playwright % 


VSCodeに拡張機能のPlaywright Test for VSCodeをインストールします。


VSCodeから先ほど作成したE2Eテストのプロジェクト・フォルダ(今回の作業ではPlaywrightとして作成)を開きます。プロジェクトが初期化されていて、雛形となるファイルが作成されています。


エクスプローラーからファイルplaywright.config.tsを選択し、以下の内容に置き換えます。chromiumのプロジェクトにviewportとstorageStateの設定を加えています。

import { defineConfig, devices } from '@playwright/test';
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// import dotenv from 'dotenv';
// import path from 'path';
// dotenv.config({ path: path.resolve(__dirname, '.env') });
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './tests',
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
// baseURL: 'http://127.0.0.1:3000',
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},
/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
viewport: { width: 1280, height: 1280 },
storageState: './.auth/state.json',
},
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },
/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
// },
],
/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// url: 'http://127.0.0.1:3000',
// reuseExistingServer: !process.env.CI,
// },
});

テスト・スクリプトを配置するフォルダtestsに、以下のファイルfixtures.tsを作成します。このファイルに、APEXアプリケーションへサインインする手順を記述しています。

BASE_URLは、先ほど作成したAPEXアプリケーションを指すURLに変更します。

import { test as base } from "@playwright/test";
import path from 'path';
import * as fs from 'fs';
/*
* プロジェクトのフォルダ直下に.authフォルダを作成し、その中にauth.jsonを作成する。
* auth.jsonの中身は以下のようにする。
* ログイン・ユーザー名とパスワードは、実際のものに置き換えること。
* {"username":"admin","password":"4fae#ae2ef3!!","sessionId":"17291688537780"}
*
* 初回実行時のために、state.jsonファイルを作成しておく。
* echo "{}" > .auth/state.json
*
* BASE_URLは、テスト実行時に使用するURLを指定する。
*/
export const authFile = path.join(__dirname, '../.auth/auth.json');
export const BASE_URL = 'http://localhost:8181/ords/r/apexdev/demonstration-emp-dept';
const stateFile = path.join(__dirname, '../.auth/state.json');
export const test = base.extend({
// Create a custom fixture
loginUser: async ({ page }, use) => {
// auth.jsonからユーザー名とパスワードを取り出す。
const auth = JSON.parse(fs.readFileSync(authFile, 'utf8'));
/*
* 最初にホーム・ページにアクセスするが、URLにsession=が含まれていないため、ログイン・ページに遷移する。
*/
await page.goto(`${BASE_URL}/home`);
/*
* ページ・作成ウィザードが生成したログイン・ページであれば、
* ページ・アイテム名がIDと同じINPUT要素が作成されている。
*/
await page.fill("input#P9999_USERNAME", auth.username);
await page.fill("input#P9999_PASSWORD", auth.password);
// await page.click("input#P9999_REMEMBER");
// サインイン・ボタンをクリックする。ボタンに静的IDとしてLOGINを設定する必要がある。
await page.click("button#LOGIN");
/*
* サインインに成功した後、ホーム・ページに遷移する。
* ページ・遷移後のURLからsessioin=の引数に設定されている
* セッションIDを取り出し、auth.jsonに保存する。
* このセッションIDを後続のテストで使用する。
*
* 完全にホーム・ページに遷移したことを確認するためにwaitForSelectorを呼び出しているが、
* もっと汎用的な方法があるはず。
*/
await page.waitForSelector('#menu-dashboard');
// URLからセッションIDを取り出す。
const homeURL = new URL(page.url());
const sessionId = homeURL.searchParams.get('session');
// auth.jsonにsessionIdとして保存する。
const newAuth = { ...auth, sessionId: sessionId };
fs.writeFileSync(authFile, JSON.stringify(newAuth));
// console.log('afer signin - auth', newAuth);
/*
* contextをstate.jsonに保存する。
*/
await page.context().storageState({ path: stateFile });
// const cookies = await page.context().cookies();
// console.log('cookies', cookies);
// Pass control back to the test
await use();
},
});
view raw fixtures.ts hosted with ❤ by GitHub

プロジェクトのフォルダの直下にフォルダ.authを作成します。認証情報を保存するファイルauth.jsonと、ブラウザの状態を保存するファイルstate.jsonを配置します。


フォルダ.auth直下にファイルauth.jsonを作成します。内容として、以下を記述します。usernamepasswordは環境に合わせて変更します。sessionIdはログイン後にテスト・スクリプトによって更新されるため、値はそのままで問題ありません。

{"username":"admin","password":"4fae#ae2ef3!!","sessionId":"17291688537780"}


フォルダ.auth直下にブラウザのステータスを保存するファイルstate.jsonを作成します。内容はとして{}を記述し、空のJSONオブジェクトが保存されている状態にします。


最後に今回実施するE2Eテストを記述したファイルapex.spec.tsを、フォルダtests以下に作成します。

import { expect } from '@playwright/test';
import { test, authFile, BASE_URL } from './fixtures.ts';
import path from 'path';
import * as fs from 'fs';
test('open Dashboard', async ({ page, loginUser }) => {
/*
* fixtures.jsに記載されているloginUserが呼び出される。
* サインインに成功した後は、ホーム・ページが開かれている。
*/
// 表示されているページにダッシュボードのカードがあることを確認する。
await page.waitForSelector('#menu-dashboard', { timeout: 5000 });
// ダッシュボードのカードをクリックする。#menu-dashboardはAPEX側に要設定。
await page.click("a#menu-dashboard");
// ダッシュボードのページが開かれていることを確認する。
await expect(page).toHaveTitle('Dashboard');
});
/*
test('verify', async ({ page }) => {
// call page without fixture.
await page.goto('http://localhost:8181/ords/apexdev/test/test');
});
*/
test('open Employees', async ({ page }) => {
/*
* loginUserは呼び出さず、サインインが継続している状態から始める。
* auth.jsonに保存されているsessionIdを使用して、ホームページを開く。
* auth.jsonは、fixtures.jsのloginUserで、サインイン時にsessionIdが更新されている。
*/
const auth = JSON.parse(fs.readFileSync(authFile, 'utf8'));
// ホーム・ページを開く。
const home_url = `${BASE_URL}/home?session=${auth.sessionId}`;
console.log(home_url);
await page.goto(home_url);
// ホーム・ページに従業員一覧のカードがあることを確認し、クリックする。#menu-employeesはAPEX側に要設定。
await page.waitForSelector('#menu-employees', { timeout: 3000 });
await page.click("a#menu-employees");
// 従業員のページが開かれていることを確認する。
await expect(page).toHaveTitle('Employees');
});
test('open Departments', async ({ page }) => {
/*
* 従業員一覧に同じ。
*/
const auth = JSON.parse(fs.readFileSync(authFile, 'utf8'));
// ホーム・ページを開く。
const home_url = `${BASE_URL}/home?session=${auth.sessionId}`;
console.log(home_url);
await page.goto(home_url);
// ホーム・ページに部門一覧のカードがあることを確認し、クリックする。#menu-departmentsはAPEX側に要設定。
await page.waitForSelector('#menu-departments', { timeout: 3000 });
await page.click("a#menu-departments");
// 部門のページが開かれていることを確認する。
await expect(page).toHaveTitle('Departments');
});
view raw apex.spec.ts hosted with ❤ by GitHub

以上でPlaywrightを使ってE2Eテストを実行する準備ができました。

作成したファイルをすべて保存し、Playwrightの拡張機能を開きます。

testsとして認識されているapex.spec.tsにある実行ボタンをクリックすることで、apex.spec.tsに記述されている一連のテストが実行されます。apex.spec.tsにはopen Dashboard、open Employees、open Departmentsの3つのテストが含まれています。

それぞれ個別に実行できますが、open Dashboardでユーザー認証を行なっている都合上、最初にopen Dashboardのテストを実行する必要があります。


今回の記事は以上になります。

Oracle APEXのアプリケーション作成の参考になれば幸いです。

2025年3月27日木曜日

Oracle Database Free 23ai 23.7にDBMS_CLOUDファミリーのパッケージをインストールする

Oracle Database 23aiのリリース・アップデート23.7より、ローカルで実行できるデータベースにCloud Developer Packagesがバンドルされました。

Oracle Database New Features - Release Update 23.7 Features

リリース・ノートによるとCloud Developer Packagesには、以下のパッケージが含まれます。Autonomous Databaseに実装されている同名のパッケージに実装されていて、こちらのパッケージには無い機能もあるようです。

DBMS_CLOUD
DBMS_CLOUD_PIPELINE
DBMS_CLOUD_REPO
DBMS_CLOUD_NOTIFICATION
DBMS_CLOUD_AI

これらのパッケージは$ORACLE_HOME/rdbms/admin以下にインストール・スクリプトが含まれていますが、データベースにインストールされてはいません。パッケージを利用するには、データベースにインストールする必要があります。

パッケージのインストール手順は、ドキュメントUtilitiesの20.2 Install DBMS_CLOUDに記載されています。

Utilities - 20.2 Installing DBMS_CLOUD

以下より、マニュアルの手順に従ってインストール作業を行ってみます。インストールする環境は、Oracle Container Registryより入手できるOracle Database Free 23aiのコンテナ・イメージより作成します。Oracle Database Freeのコンテナ・イメージはARM64、AMD64版ともに23.7に更新されています。

コンテナの実行には、Apple SiliconのMac上でpodmanを使用します。

最初にOracle Database Free 23aiのコンテナを作成し実行します。コンテナの名前はoradbとします。
podman run -d --name oradb -p 1521:1521 container-registry.oracle.com/database/free:latest

% podman run -d --name oradb -p 1521:1521  container-registry.oracle.com/database/free:latest

5966443f8868e0372d28bbec70e8cb748413a0427a8f8c4300740be8246de324

% 


コンテナoradbが利用可能になったら、SYSのパスワードを設定します。
podman exec -it oradb ./setPassword.sh [SYSのパスワード]

% podman exec -it oradb ./setPassword.sh [SYSのパスワード]

The Oracle base remains unchanged with value /opt/oracle


SQL*Plus: Release 23.0.0.0.0 - Production on Thu Mar 27 04:10:38 2025

Version 23.7.0.25.01


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



Connected to:

Oracle Database 23ai Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free

Version 23.7.0.25.01


SQL> 

User altered.


SQL> 

User altered.


SQL> 

Session altered.


SQL> 

User altered.


SQL> Disconnected from Oracle Database 23ai Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free

Version 23.7.0.25.01

% 


DBMS_CLOUDのインストール作業を実施するために、コンテナに接続します。
podman exec -it oradb bash

% podman exec -it oradb bash

bash-4.4$ 


マニュアルの手順にあるcatclouduser.sqlを実行します。CDBおよびPDBにインストールするため、catcon.plを使用します。your-passwordの部分は先ほど設定したSYSのパスワードに置き換えます。
$ORACLE_HOME/perl/bin/perl $ORACLE_HOME/rdbms/admin/catcon.pl -u sys/your-password -force_pdb_mode 'READ WRITE' -b dbms_cloud_install -d $ORACLE_HOME/rdbms/admin/ -l /tmp catclouduser.sql

bash-4.4$ $ORACLE_HOME/perl/bin/perl $ORACLE_HOME/rdbms/admin/catcon.pl -u sys/[SYSのパスワード] -force_pdb_mode 'READ WRITE' -b dbms_cloud_install -d $ORACLE_HOME/rdbms/admin/ -l /tmp catclouduser.sql

catcon::set_log_file_base_path: ALL catcon-related output will be written to [/tmp/dbms_cloud_install_catcon_1021.lst]


catcon::set_log_file_base_path: catcon: See [/tmp/dbms_cloud_install*.log] files for output generated by scripts


catcon::set_log_file_base_path: catcon: See [/tmp/dbms_cloud_install_*.lst] files for spool files, if any


catcon::get_kill_sess_script_info: query produced 2 rows instead of expected 3 rows corresponding to processes 1070, 1071, 1072


catcon.pl: completed successfully

bash-4.4$ 


続けてdbms_cloud_install.sqlを実行します。こちらも同様にyour-passwordの部分をSYSのパスワードに置き換えます。
$ORACLE_HOME/perl/bin/perl $ORACLE_HOME/rdbms/admin/catcon.pl -u sys/your-password -force_pdb_mode 'READ WRITE' -b dbms_cloud_install -d $ORACLE_HOME/rdbms/admin/ -l /tmp dbms_cloud_install.sql

bash-4.4$ $ORACLE_HOME/perl/bin/perl $ORACLE_HOME/rdbms/admin/catcon.pl -u sys/[SYSのパスワード] -force_pdb_mode 'READ WRITE' -b dbms_cloud_install -d $ORACLE_HOME/rdbms/admin/ -l /tmp dbms_cloud_install.sql

catcon::set_log_file_base_path: ALL catcon-related output will be written to [/tmp/dbms_cloud_install_catcon_1226.lst]


catcon::set_log_file_base_path: catcon: See [/tmp/dbms_cloud_install*.log] files for output generated by scripts


catcon::set_log_file_base_path: catcon: See [/tmp/dbms_cloud_install_*.lst] files for spool files, if any


catcon.pl: completed successfully

bash-4.4$ 


インストールされたデータベース・オブジェクトのステータスを確認します。

最初にCDBに接続し、以下のSELECT文を実行します。
select con_id, owner, object_name, status, sharing, oracle_maintained from cdb_objects where object_name like 'DBMS_CLOUD%';
STATUSがすべてVALIDであれば、オブジェクトは正常に作成されています。

bash-4.4$ sqlplus / as sysdba


SQL*Plus: Release 23.0.0.0.0 - Production on Thu Mar 27 04:28:57 2025

Version 23.7.0.25.01


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



Connected to:

Oracle Database 23ai Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free

Version 23.7.0.25.01


SQL> set pages 1000 lines 180 trims on trimo on

SQL> col con_id format 9999

SQL> col owner format a18

SQL> col object_name format a30

SQL> col status format a8

SQL> col sharing format a16

SQL> col oracle_maintained format a3

SQL> select con_id, owner, object_name, status, sharing, oracle_maintained from cdb_objects where object_name like 'DBMS_CLOUD%';


CON_ID OWNER   OBJECT_NAME STATUS   SHARING   ORA

------ ------------------ ------------------------------ -------- ---------------- ---

     1 PUBLIC   DBMS_CLOUD VALID   METADATA LINK    Y

     1 PUBLIC   DBMS_CLOUD_AI  VALID   METADATA LINK    Y

     1 PUBLIC   DBMS_CLOUD_CAPABILITY  VALID   METADATA LINK    Y

     1 PUBLIC   DBMS_CLOUD_CORE VALID   METADATA LINK    Y

     1 PUBLIC   DBMS_CLOUD_INTERNAL VALID   METADATA LINK    Y

     1 PUBLIC   DBMS_CLOUD_NOTIFICATION VALID   METADATA LINK    Y

     1 PUBLIC   DBMS_CLOUD_OCI_REGIONS VALID   METADATA LINK    Y

     1 PUBLIC   DBMS_CLOUD_PIPELINE VALID   METADATA LINK    Y

     1 PUBLIC   DBMS_CLOUD_PIPELINE_INTERNAL VALID   METADATA LINK    Y

     1 PUBLIC   DBMS_CLOUD_REPO VALID   METADATA LINK    Y

     1 PUBLIC   DBMS_CLOUD_TYPES VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_AI  VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_AI  VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_AI_PROFILE$ VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_AI_PROFILE_ATTR$ VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_AI_PROFILE_SCHEMA$  VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_CAPABILITIES$ VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_CAPABILITIES_UNIQUE VALID   NONE   Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_CAPABILITY  VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_CAPABILITY  VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_CLOUD_STORE_UNIQUE  VALID   NONE   Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_CONFIG_PARAM VALID   DATA LINK   Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_CONFIG_PARAM$ VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_CORE VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_CORE VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_FILE_SYSTEM$ VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_FILE_SYSTEM_UNIQUE  VALID   NONE   Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_INTERNAL VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_INTERNAL VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_NOTIFICATION VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_NOTIFICATION VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_OCI_REGIONS VALID   DATA LINK   Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_OCI_REGIONS$ VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_OCI_REGIONS_UNIQUE  VALID   NONE   Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_PARAM_UNIQUE VALID   NONE   Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE$ VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_ATTR$ VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_ATTR_I1$ VALID   NONE   Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_FILE$ VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_FILE_I1$ VALID   NONE   Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_I1$ VALID   NONE   Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_INTERNAL VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_INTERNAL VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_REPO VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_REPO VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_REQUEST VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_REQUEST VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_REST_API_RESULTS$ VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_STORE VALID   DATA LINK   Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_STORE$ VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_TASK VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_TASK VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_TASK$ VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_TASKS VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_TASK_CLASS  VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_TASK_CLASS$ VALID   METADATA LINK    Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_TASK_CLASS_UNIQUE VALID   NONE   Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_TASK_CLEANUP VALID   NONE   Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_TASK_ID VALID   NONE   Y

     1 C##CLOUD$SERVICE   DBMS_CLOUD_TYPES VALID   METADATA LINK    Y

     3 PUBLIC   DBMS_CLOUD VALID   METADATA LINK    Y

     3 PUBLIC   DBMS_CLOUD_AI  VALID   METADATA LINK    Y

     3 PUBLIC   DBMS_CLOUD_CAPABILITY  VALID   METADATA LINK    Y

     3 PUBLIC   DBMS_CLOUD_CORE VALID   METADATA LINK    Y

     3 PUBLIC   DBMS_CLOUD_INTERNAL VALID   METADATA LINK    Y

     3 PUBLIC   DBMS_CLOUD_NOTIFICATION VALID   METADATA LINK    Y

     3 PUBLIC   DBMS_CLOUD_OCI_REGIONS VALID   METADATA LINK    Y

     3 PUBLIC   DBMS_CLOUD_PIPELINE VALID   METADATA LINK    Y

     3 PUBLIC   DBMS_CLOUD_PIPELINE_INTERNAL VALID   METADATA LINK    Y

     3 PUBLIC   DBMS_CLOUD_REPO VALID   METADATA LINK    Y

     3 PUBLIC   DBMS_CLOUD_TYPES VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_AI  VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_AI  VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_AI_PROFILE$ VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_AI_PROFILE_ATTR$ VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_AI_PROFILE_SCHEMA$  VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_CAPABILITIES$ VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_CAPABILITIES_UNIQUE VALID   NONE   Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_CAPABILITY  VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_CAPABILITY  VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_CLOUD_STORE_UNIQUE  VALID   NONE   Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_CONFIG_PARAM VALID   DATA LINK   Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_CONFIG_PARAM$ VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_CORE VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_CORE VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_FILE_SYSTEM$ VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_FILE_SYSTEM_UNIQUE  VALID   NONE   Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_INTERNAL VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_INTERNAL VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_NOTIFICATION VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_NOTIFICATION VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_OCI_REGIONS VALID   DATA LINK   Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_OCI_REGIONS$ VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_OCI_REGIONS_UNIQUE  VALID   NONE   Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_PARAM_UNIQUE VALID   NONE   Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE$ VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_ATTR$ VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_ATTR_I1$ VALID   NONE   Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_FILE$ VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_FILE_I1$ VALID   NONE   Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_I1$ VALID   NONE   Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_INTERNAL VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_INTERNAL VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_REPO VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_REPO VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_REQUEST VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_REQUEST VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_REST_API_RESULTS$ VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_STORE VALID   DATA LINK   Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_STORE$ VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_TASK VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_TASK VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_TASK$ VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_TASKS VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_TASK_CLASS  VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_TASK_CLASS$ VALID   METADATA LINK    Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_TASK_CLASS_UNIQUE VALID   NONE   Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_TASK_CLEANUP VALID   NONE   Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_TASK_ID VALID   NONE   Y

     3 C##CLOUD$SERVICE   DBMS_CLOUD_TYPES VALID   METADATA LINK    Y


128 rows selected.


SQL> 


CDBビューを検索しているのですでに確認ずみではありますが、PDBとして作成されているFREEPDB1に接続し、以下のSELECT文を実行します。
select owner, object_name, status, sharing, oracle_maintained from dba_objects where object_name like 'DBMS_CLOUD%';

SQL> alter session set container = freepdb1;


Session altered.


SQL> select owner, object_name, status, sharing, oracle_maintained from dba_objects where object_name like 'DBMS_CLOUD%';


OWNER   OBJECT_NAME   STATUS   SHARING     ORA

------------------ ------------------------------ -------- ---------------- ---

PUBLIC   DBMS_CLOUD   VALID    METADATA LINK    Y

PUBLIC   DBMS_CLOUD_AI   VALID    METADATA LINK    Y

PUBLIC   DBMS_CLOUD_CAPABILITY   VALID    METADATA LINK    Y

PUBLIC   DBMS_CLOUD_CORE   VALID    METADATA LINK    Y

PUBLIC   DBMS_CLOUD_INTERNAL   VALID    METADATA LINK    Y

PUBLIC   DBMS_CLOUD_NOTIFICATION   VALID    METADATA LINK    Y

PUBLIC   DBMS_CLOUD_OCI_REGIONS   VALID    METADATA LINK    Y

PUBLIC   DBMS_CLOUD_PIPELINE   VALID    METADATA LINK    Y

PUBLIC   DBMS_CLOUD_PIPELINE_INTERNAL   VALID    METADATA LINK    Y

PUBLIC   DBMS_CLOUD_REPO   VALID    METADATA LINK    Y

PUBLIC   DBMS_CLOUD_TYPES   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_AI   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_AI   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_AI_PROFILE$   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_AI_PROFILE_ATTR$   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_AI_PROFILE_SCHEMA$  VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_CAPABILITIES$   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_CAPABILITIES_UNIQUE VALID    NONE     Y

C##CLOUD$SERVICE   DBMS_CLOUD_CAPABILITY   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_CAPABILITY   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_CLOUD_STORE_UNIQUE  VALID    NONE     Y

C##CLOUD$SERVICE   DBMS_CLOUD_CONFIG_PARAM   VALID    DATA LINK     Y

C##CLOUD$SERVICE   DBMS_CLOUD_CONFIG_PARAM$   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_CORE   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_CORE   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_FILE_SYSTEM$   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_FILE_SYSTEM_UNIQUE  VALID    NONE     Y

C##CLOUD$SERVICE   DBMS_CLOUD_INTERNAL   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_INTERNAL   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_NOTIFICATION   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_NOTIFICATION   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_OCI_REGIONS   VALID    DATA LINK     Y

C##CLOUD$SERVICE   DBMS_CLOUD_OCI_REGIONS$   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_OCI_REGIONS_UNIQUE  VALID    NONE     Y

C##CLOUD$SERVICE   DBMS_CLOUD_PARAM_UNIQUE   VALID    NONE     Y

C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE$   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_ATTR$   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_ATTR_I1$   VALID    NONE     Y

C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_FILE$   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_FILE_I1$   VALID    NONE     Y

C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_I1$   VALID    NONE     Y

C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_INTERNAL   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_PIPELINE_INTERNAL   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_REPO   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_REPO   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_REQUEST   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_REQUEST   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_REST_API_RESULTS$   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_STORE   VALID    DATA LINK     Y

C##CLOUD$SERVICE   DBMS_CLOUD_STORE$   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_TASK   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_TASK   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_TASK$   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_TASKS   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_TASK_CLASS   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_TASK_CLASS$   VALID    METADATA LINK    Y

C##CLOUD$SERVICE   DBMS_CLOUD_TASK_CLASS_UNIQUE   VALID    NONE     Y

C##CLOUD$SERVICE   DBMS_CLOUD_TASK_CLEANUP   VALID    NONE     Y

C##CLOUD$SERVICE   DBMS_CLOUD_TASK_ID   VALID    NONE     Y

C##CLOUD$SERVICE   DBMS_CLOUD_TYPES   VALID    METADATA LINK    Y


64 rows selected.


SQL> 


マニュアルの20.3からSSL Walletの作成について記載されていますが、今回はOracle Database 23aiから利用できるsystem:を使うことにします。ウォレットとしてsystem:を指定することで、OSにインストールされているSSL証明書が参照されます。そのため、データベース側でSSL Walletを準備する必要はありません。

20.5のセクションで解説されているACEを設定します。ACEはcatclouduser.sqlの実行で作成されたユーザーC##CLOUD$SERVICEをプリンシパルとして作成します。

ACEはCDB(コンテナとしてはCDB$ROOT)とすべてのPDB(今回はFREEPDB1)に対して、それぞれ作成します

マニュアルにはSSL WalletのアクセスについてもACEを作成していますが、今回はsystem:の指定を想定しているため、このACEは省略します。

CDB$ROOTに接続し、以下を実行します。
begin
    dbms_network_acl_admin.append_host_ace(
        host => '*',
        ace => xs$ace_type(
            privilege_list => xs$name_list('http','http_proxy'),
            principal_name => 'C##CLOUD$SERVICE',
            principal_type => xs_acl.ptype_db
        )
    );
    commit;
end;
/

SQL> alter session set container = cdb$root;


Session altered.


SQL> begin

    dbms_network_acl_admin.append_host_ace(

        host => '*',

        ace => xs$ace_type(

            privilege_list => xs$name_list('http','http_proxy'),

            principal_name => 'C##CLOUD$SERVICE',

            principal_type => xs_acl.ptype_db

        )

    );

    commit;

end;

/  2    3    4    5    6    7    8    9   10   11   12  


PL/SQL procedure successfully completed.


SQL> 


PDBのFREEPDB1へ接続を切り替え、同じスクリプトを実行します。

SQL> alter session set container = freepdb1;


Session altered.


SQL> begin

    dbms_network_acl_admin.append_host_ace(

        host => '*',

        ace => xs$ace_type(

            privilege_list => xs$name_list('http','http_proxy'),

            principal_name => 'C##CLOUD$SERVICE',

            principal_type => xs_acl.ptype_db

        )

    );

    commit;

end;

/  2    3    4    5    6    7    8    9   10   11   12  


PL/SQL procedure successfully completed.


SQL> 


20.6で紹介されている検証用のスクリプトを実行します。

以下のコードをファイルverify_dbms_cloud.sqlとして作成し、CDBに接続して実行します。wallet_pathにsystem:を使用するように、マニュアルにあるコードを改変しています。

define clouduser=C##CLOUD$SERVICE
-- CUSTOMER SPECIFIC SETUP, NEEDS TO BE PROVIDED BY THE CUSTOMER
-- - SSL Wallet directory and password
-- define sslwalletdir=<Set SSL Wallet Directory>
-- define sslwalletpwd=<Set SSL Wallet password>
-- In environments w/ a proxy, you need to set the proxy in the verification code
-- define proxy_uri=<your proxy URI address>
-- create and run this procedure as owner of the ACLs, which is the future owner
-- of DBMS_CLOUD
CREATE OR REPLACE PROCEDURE &clouduser..GET_PAGE(url IN VARCHAR2) AS
request_context UTL_HTTP.REQUEST_CONTEXT_KEY;
req UTL_HTTP.REQ;
resp UTL_HTTP.RESP;
data VARCHAR2(32767) default null;
err_num NUMBER default 0;
err_msg VARCHAR2(4000) default null;
BEGIN
--
-- wallet_pathはsystem:固定.
--
-- Create a request context with its wallet and cookie table
request_context := UTL_HTTP.CREATE_REQUEST_CONTEXT(
wallet_path => 'system:'
);
-- Make a HTTP request using the private wallet and cookie
-- table in the request context
-- uncomment if proxy is required
-- UTL_HTTP.SET_PROXY('&proxy_uri', NULL);
req := UTL_HTTP.BEGIN_REQUEST(url => url,request_context => request_context);
resp := UTL_HTTP.GET_RESPONSE(req);
DBMS_OUTPUT.PUT_LINE('valid response');
EXCEPTION
WHEN OTHERS THEN
err_num := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 3800);
DBMS_OUTPUT.PUT_LINE('possibly raised PLSQL/SQL error: ' ||err_num||' - '||err_msg);
UTL_HTTP.END_RESPONSE(resp);
data := UTL_HTTP.GET_DETAILED_SQLERRM ;
IF data IS NOT NULL THEN
DBMS_OUTPUT.PUT_LINE('possibly raised HTML error: ' ||data);
END IF;
END;
/
set serveroutput on
BEGIN
&clouduser..GET_PAGE('https://objectstorage.eu-frankfurt-1.oraclecloud.com');
END;
/
set serveroutput off
drop procedure &clouduser..GET_PAGE;
Enter value for proxy_uriとして入力が求められますが、UTL_HTTP.SET_PROXYの呼び出しはコメント・アウトされているため、何を入力しても結果に影響しません。

スクリプトの途中でvalid responseと表示されていれば、パッケージDBMS_CLOUDのインストールの検証は成功したことになります。

bash-4.4$ sqlplus / as sysdba @verify_dbms_cloud.sql


SQL*Plus: Release 23.0.0.0.0 - Production on Thu Mar 27 04:56:04 2025

Version 23.7.0.25.01


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



Connected to:

Oracle Database 23ai Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free

Version 23.7.0.25.01


old   1: CREATE OR REPLACE PROCEDURE &clouduser..GET_PAGE(url IN VARCHAR2) AS

new   1: CREATE OR REPLACE PROCEDURE C##CLOUD$SERVICE.GET_PAGE(url IN VARCHAR2) AS

Enter value for proxy_uri: 

old  23: --    UTL_HTTP.SET_PROXY('&proxy_uri', NULL);

new  23: --    UTL_HTTP.SET_PROXY('', NULL);


Procedure created.


old   2:     &clouduser..GET_PAGE('https://objectstorage.eu-frankfurt-1.oraclecloud.com');

new   2:     C##CLOUD$SERVICE.GET_PAGE('https://objectstorage.eu-frankfurt-1.oraclecloud.com');

valid response


PL/SQL procedure successfully completed.


old   1: drop procedure &clouduser..GET_PAGE

new   1: drop procedure C##CLOUD$SERVICE.GET_PAGE


Procedure dropped.


SQL> 


実際にパッケージを使ってみます。テストに使用するデータベース・ユーザーを、FREEPDB1にtestuserとして作成します。
alter session set container = freepdb1;
create user testuser default tablespace users temporary tablespace temp identified by testuser;
alter user testuser quota unlimited on users;
grant connect, resource, db_developer_role to testuser;
grant execute on dbms_cloud to testuser;
grant execute on dbms_cloud_pipeline to testuser;
grant execute on dbms_cloud_repo to testuser;
grant execute on dbms_cloud_notification to testuser;
grant execute on dbms_cloud_ai to testuser;

SQL> alter session set container = freepdb1;


Session altered.


SQL> create user testuser default tablespace users temporary tablespace temp identified by testuser;


User created.


SQL> alter user testuser quota unlimited on users;


User altered.


SQL> grant connect, resource, db_developer_role to testuser;


Grant succeeded.


SQL> grant execute on dbms_cloud to testuser;


Grant succeeded.


SQL> grant execute on dbms_cloud_pipeline to testuser;


Grant succeeded.


SQL> grant execute on dbms_cloud_repo to testuser;


Grant succeeded.


SQL> grant execute on dbms_cloud_notification to testuser;


Grant succeeded.


SQL> grant execute on dbms_cloud_ai to testuser;


Grant succeeded.


SQL> 


テストユーザーtestuserにてHTTPのコールアウトができるように、ACEを追加します。先ほどのスクリプトをプリンシパルをTESTUSERに変更して実行します。
begin
    dbms_network_acl_admin.append_host_ace(
        host => '*',
        ace => xs$ace_type(
            privilege_list => xs$name_list('http','http_proxy'),
            principal_name => 'TESTUSER',
            principal_type => xs_acl.ptype_db
        )
    );
    commit;
end;
/

SQL> begin

    dbms_network_acl_admin.append_host_ace(

        host => '*',

        ace => xs$ace_type(

            privilege_list => xs$name_list('http','http_proxy'),

            principal_name => 'TESTUSER',

            principal_type => xs_acl.ptype_db

        )

    );

    commit;

end;

/  2    3    4    5    6    7    8    9   10   11   12  


PL/SQL procedure successfully completed.


SQL> 


以上でTESTUSERの準備は完了です。

PDBのFREEPDB1にユーザーTESTUSERで接続して、Select AIを呼び出してみます。

作業は、オラクルのドキュメントExamples of Using Select AIExample: Select AI with OpenAIに沿った手順で実施します。OpenAIのAPIキーを取得していることが前提です。

コンテナの中でsqlplusを使うのは面倒です。コンテナのポート1521はホストのポート1521にマップしているため、ホストのmacOSからSQLclで接続して作業します。

% sql testuser/testuser@localhost/freepdb1



SQLcl: 木 3月 27 14:15:00 2025のリリース24.4 Production


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


接続先:

Oracle Database 23ai Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free

Version 23.7.0.25.01


SQL> 


最初に表EMPを作成します。Select AIによるSQLの作成と実行を確認するだけなので、表だけを作成しデータは投入しません。
create table emp (empno number primary key, ename varchar2(80), sal number, comm number);

SQL> create table emp (empno number primary key, ename varchar2(80), sal number, comm number);


Table EMPは作成されました。


SQL>


OpenAIのAPI呼び出しに使用するクリデンシャルを作成します。APIキーは取得済みとします。
begin
  dbms_cloud.create_credential(
    credential_name => 'OPENAI_CRED'
    ,username => 'OPENAI'
    ,password => 'OpenAIのAPIキー'
  );
end;
/

SQL> begin

  2    dbms_cloud.create_credential(

  3      credential_name => 'OPENAI_CRED'

  4      ,username => 'OPENAI'

  5      ,password => 'OpenAIのAPIキー'

  6    );

  7  end;

  8* /


PL/SQLプロシージャが正常に完了しました。


SQL>


Select AIのプロファイルを作成します。
begin
  dbms_cloud_ai.create_profile(
    profile_name => 'OPENAI'
    ,attributes => '{"provider": "openai", "credential_name": "OPENAI_CRED",
"object_list": [{ "owner": "TESTUSER", "name": "EMP" }], "conversation": "true" }');
end;
/

SQL> begin

  2    dbms_cloud_ai.create_profile(

  3      profile_name => 'OPENAI'

  4      ,attributes => '{"provider": "openai", "credential_name": "OPENAI_CRED",

  5  "object_list": [{ "owner": "TESTUSER", "name": "EMP" }], "conversation": "true" }');

  6  end;

  7* /


PL/SQLプロシージャが正常に完了しました。


SQL>


作成したプロファイルをセットします。
begin
  dbms_cloud_ai.set_profile('OPENAI');
end;
/

SQL> begin

  2  dbms_cloud_ai.set_profile('OPENAI');

  3  end;

  4* /


PL/SQLプロシージャが正常に完了しました。


SQL>


セットされたプロファイルを確認します。
select dbms_cloud_ai.get_profile() from dual;

SQL> select dbms_cloud_ai.get_profile() from dual;


DBMS_CLOUD_AI.GET_PROFILE()    

______________________________ 

"OPENAI"                       


SQL>


Select AIを呼び出してSQLを生成します。
select ai showsql how many employees exist;

SQL> select ai showsql how many employees exist;


RESPONSE                            

___________________________________ 

SELECT COUNT(*) AS num_employees

FROM "TESTUSER"."EMP"    


SQL> 


以上で、インストールしたDBMS_CLOUD関連パッケージの動作が確認できました。

Select AIの呼び出しでは不要でしたが、場合によってはHTTPリクエストが発行されるまえ(DBMS_CLOUD.SEND_REQUESTなど)の前にウォレットの設定が必要な場合があるようです。そのようなケースではあらかじめUTL_HTTP.SET_WALLETを実行しておきます。
utl_http.set_wallet('system:');

今回の記事は以上になります。


 追記

DBMS_CLOUD_REPOは以下の記事で使用しています。ローカルにインストールしたアプリケーションを動かしたところ、概ね動きました。

DBMS_CLOUD_PIPELINEは以下の記事で動作を確認しています。こちらもローカルで概ね動きました。
パッケージDBMS_CLOUD_PIPELINEを使用してビューAPEX_WORKSPACE_ACTIVITY_LOGの内容をオフロードする

追記終了