データ・ソースへの接続の管理

データ・ソースへの接続を作成、更新、削除および共有できます。DVコンテンツ作成者のアクセス権を持つOracle Analyticsユーザーとして、次のアクションを実行できます。

トピック:

データ・ソースへの接続の作成

データ・ソース内のデータを分析できるように接続を作成できます。

  1. ホーム・ページで、「作成」をクリックしてから「接続」をクリックします。
  2. 「接続タイプを選択してください」ダイアログ・ボックスで、必要な接続タイプのアイコンをクリックします。たとえば、「Oracle Database」です。
  3. ホスト、ポート、ユーザー名、パスワード、サービス名などの必要な接続情報を入力します。
  4. オプション: 接続の「認証」オプションを選択します。
    • 常にこれらの資格証明を使用 - Oracle Analyticsは、接続に指定されたログイン名およびパスワードを常に使用します。ユーザーがログインを求められることはありません。
    • ユーザーは自分の資格証明の入力が必要 - Oracle Analyticsはデータ・ソースに対する自分のユーザー名とパスワードを入力するようユーザーに求めます。ユーザーは、権限およびロールが割り当てられているデータのみにアクセスできます。
    • (Oracle Analyticsでこのデータベース・タイプに対して偽装がサポートされている場合に表示)アクティブなユーザーの資格証明を使用 - Oracle Analyticsは、データにアクセスするためにサインインするようユーザーに求めません。Oracle Analyticsへのサインインに使用した同じ資格証明がこのデータ・ソースへのアクセスにも使用されます。
  5. リモート・データベースに接続している場合は、「リモート・データ接続の使用」をクリックします。
    リモート・データベースにアクセスできることを管理者に確認してください。
  6. セマンティック・モデラーまたはモデル管理ツールでこれらの接続を使用する場合は、「システム接続」をクリックします。データベース接続オプションを参照してください。
  7. 「保存」をクリックします。
    これで、この接続からのワークブックまたはデータセットの作成を開始できるようになりました。たとえば、ホーム・ページで、「作成」をクリックしてから「データ・セット」をクリックし、直前に作成した接続を選択します。

データ・ソース接続の編集

データ・ソースの接続詳細を更新できます。

Oracle DatabaseへのSSL接続を編集しており、新しいcwallet.ssoファイルを使用する必要がある場合は、「クライアント・ウォレット」フィールドで「選択」をクリックし、cwallet.ssoファイルを参照します。cwallet.ssoファイルの場所については、管理者に問い合せてください。

  1. ホーム・ページで、ナビゲータをクリックし、「データ」「接続」の順にクリックします。
  2. 編集する接続にカーソルを合せます。強調表示された接続の右側で、「アクション」をクリックし、「検査」を選択します。
  3. 「検査」ダイアログで、接続の詳細を編集します。
    接続用の現在のパスワードまたは論理SQLを表示できません。これらを変更する必要がある場合、新しい接続を作成します。
  4. 「保存」をクリックします。

データ・ソース接続の削除

Oracle Analytics Cloudからデータ・ソース接続を削除できます。たとえば、データベースのパスワードが変更された場合は、データベース接続を削除して新しい接続を作成する必要があります。

接続にデータセットが含まれている場合は、接続を削除する前にそれらのデータセットを削除する必要があります。

  1. データ・ページに移動し、「接続」を選択します。
  2. 削除する接続にカーソルを合せます。強調表示された接続の右側で、「アクション」をクリックし、「削除」を選択します。
  3. 「はい」をクリックします。

データ・ソース接続の共有

作成または管理するデータ・ソース接続にアクセス権限を割り当てることができます。

  1. ホーム・ページで、「ナビゲータ」をクリックします。「データ」「接続」の順にクリックします。
  2. 共有する接続にカーソルを合せ、「アクション」をクリックし、「検査」を選択します。
  3. 「アクセス」をクリックし、タブを使用してアクセス権を付与します:
    • すべて - 個々のユーザーまたはロールと接続を共有します。

    • ユーザー - 個々のユーザーと接続を共有します。

    • ロール - アプリケーション・ロール(BIコンシューマなど)と接続を共有し、そのロールを持つすべてのユーザーが接続を使用できるようにします。

  4. 「追加」ボックスを使用し、ユーザーまたはロールを検索して選択します。
    ユーザーまたはロールは、デフォルトの権限「読取り専用」が付与されて、下のリストに表示されます。
  5. デフォルトの権限を変更するには、次のいずれかを選択します:
    • フル・コントロール - ユーザーまたはロールは、接続を使用してデータベースの作成、接続の変更、接続名の変更、接続の削除を実行できます。また、接続の権限を変更することもできます。
    • 読取り/書込み - ユーザーまたはロールは、接続を使用してデータベースの作成、接続の変更、接続名の変更を実行できます(接続の削除はできません)。
    • 読取り専用 - ユーザーまたはロールは、接続を使用してデータセットを作成できますが、接続詳細の変更はできません。
  6. 「保存」をクリックします。
ユーザーが次回ログインすると、共有した接続を使用してそのデータベースのデータをビジュアル化できます。

データベース接続オプション

「接続の作成」ダイアログまたは「検査」ダイアログを使用して接続詳細を指定する際、一部のデータベース・タイプには追加の構成オプションがあります。

一般オプション

  • Oracle Databasesへの接続を作成する場合、「接続タイプ」オプションを使用して、2つの方法で接続できます。
    • 基本 - データベースの「ホスト」「ポート」および「サービス名」を指定します。
    • 詳細 - 「接続文字列」フィールドで、RACクラスタ内で実行されているデータベースの単一クライアント・アクセス名(SCAN)を指定します。例:

      sales.example.com =(DESCRIPTION= (ADDRESS_LIST= (LOAD_BALANCE=on)(FAILOVER=ON) (ADDRESS=(PROTOCOL=tcp)(HOST=123.45.67.111)(PORT=1521)) (ADDRESS=(PROTOCOL=tcp)(HOST=123.45.67.222)(PORT=1521)) (ADDRESS=(PROTOCOL=tcp)(HOST=123.45.67.333)(PORT=1521))) (CONNECT_DATA=(SERVICE_NAME= salesservice.example.com)))

  • 一括レプリケーションの有効化 - ワークブックのデータセットをロードする場合は、このオプションをオフにして一括レプリケーションを無視します。このオプションは、あるデータベースから別のデータベースにデータをレプリケーションするデータ・アナリストと上級ユーザーのために予約されています。

認証オプション

  • 常にこれらの資格証明を使用 - Oracle Analyticsは、接続に指定されたログイン名およびパスワードを常に使用します。ユーザーがログインを求められることはありません。
  • ユーザーは自分の資格証明の入力が必要 - Oracle Analyticsはデータ・ソースに対する自分のユーザー名とパスワードを入力するようユーザーに求めます。ユーザーは、権限およびロールが割り当てられているデータのみにアクセスできます。
  • (Oracle Analyticsでこのデータベース・タイプに対して偽装がサポートされている場合に表示)アクティブなユーザーの資格証明を使用 - Oracle Analyticsは、データにアクセスするためにサインインするようユーザーに求めません。Oracle Analyticsへのサインインに使用した同じ資格証明がこのデータ・ソースへのアクセスにも使用されます。

システム接続

「コピー」をクリックし、接続のオブジェクトIDをコピーします。ビジネス・モデラーでは、モデル管理ツール(「接続プール」ダイアログ)でデータ接続を識別して使用できるよう、オブジェクトIDを貼り付けられます。

ノート: 初めて接続を作成する際に「システム接続」をクリックしない場合は、後になってデータ・モデラーで接続の詳細を使用する際に、新しい接続を作成して、「システム接続」を選択する必要があります。つまり、後から接続を編集して、このオプションを選択することはできません。

データベース接続の制限

データベース接続を作成する前に、データベース接続要件を理解します。

Oracle Analyticsに表示されるデータベース表の最大数は10,000です。追加の表が必要な場合、分析対象の特定のオブジェクトへのアクセス権を持つデータベース・ユーザーの作成をデータベース管理者に依頼し、データベース接続の作成時にそのユーザーの資格証明を指定することをお薦めします。

大文字、小文字、または大/小文字混在のデータへの接続

Oracleデータベース、Oracle Autonomous Data Warehouse、Oracle Transaction Processing、Snowflake、SQL ServerまたはMy SQLに接続している場合は、表または列名の大文字、小文字、または大/小文字混在のデータを読み取れるように、デフォルトの引用識別子を変更できます。

たとえば、引用識別子として二重引用符を選択できます。Oracle Analyticsは、select EfG_Field from AbCd;を発行する(これは失敗します)かわりに、基になるSQL文select "EfG_Field" from "AbCd";に二重引用符を追加します。
  1. ホーム・ページで、「作成」をクリックしてから「接続」をクリックします。
  2. 拡張プロパティをサポートするデータベース・タイプの1つをクリックします。
    サポートされているデータベースは、Oracle、Oracle Autonomous Data Warehouse、SnowflakeおよびMy SQLです。
  3. 接続詳細を指定してから、接続を保存します。
  4. ホーム・ページで、「ナビゲータ」をクリックしてから「データ」「接続」の順にクリックします。
  5. ステップ2で保存した接続にカーソルを合せ、「アクション」をクリックし、「検査」をクリックします。
  6. 「拡張」をクリックし、「引用識別子」オプションを使用して、データベースで使用される引用識別子を選択します。

    たとえば、「二重引用符」(" ")を選択できます。Oracle Analyticsは、select EfG_Field from AbCd;を発行するかわりに基になるSQL文select "EfG_Field" from "AbCd";に二重引用符を追加します。

    注:

    「システム接続」オプションが選択された状態で接続が作成された場合、「拡張」オプションは表示されません。「拡張」オプションは、システム接続ではサポートされません。
  7. 「保存」をクリックします。

REST APIを使用した接続の管理

Oracle Analytics CloudのREST APIを使用すると、ある範囲のデータ・ソースに対する接続をプログラムで管理できます。たとえば、テストと本番の両方のOracle Analytics Cloud環境に、同じ接続のセットを作成(または変更)するスクリプトを作成するような場合です。

接続REST APIについて

REST APIを使用して、データ・ソースのある範囲の接続を作成、更新、削除できます。このトピックでは、REST APIを使用して管理できるデータ・ソース接続のタイプをリストします。

注:

Oracle Analytics Cloud REST APIに、各REST APIの詳しい情報が記載されています。接続RESTエンドポイント」を参照してください。

サポートされるデータ・ソース

  • Oracle Database
  • Oracle Autonomous Data Warehouse
  • Oracle Essbase
  • MySQL
  • PostgreSQL
  • スノーフレーク
  • SQL Server
  • Vertica

接続パラメータ

必要な接続パラメータは、データ・ソースごとに異なります。REST APIを使用して接続を作成または更新する場合は、ご使用のデータ・ソースに必要なJSONペイロード書式を把握する必要があります。データ・ソースのサンプルのJSONペイロードを参照してください。

REST APIを使用した接続管理の一般的なワークフロー

ここでは、Oracle Analytics CloudのREST APIを使用して、プログラムによる接続の管理を開始するための一般的な作業を示します。REST APIを初めて使用する場合は、次の作業をガイドにして進めてください。

タスク 説明 REST APIのドキュメント
前提条件の把握

前提条件の複数のタスクを把握して実行します。

REST APIを使用してデータ接続を管理するには、ワークブックを作成する権限とOracle Analytics Cloudのデータに接続する権限(DVコンテンツ作成者)が必要です。

前提条件
OAuth 2.0トークン認証の把握 Oracle Analytics Cloudでの認証と認可は、Oracle Identity Cloud Serviceで管理されています。Oracle Analytics CloudのREST APIにアクセスするには、認可に使用するOAuth 2.0アクセス・トークンが必要です。 OAuth 2.0トークン認証
サポートされるデータ・ソースの把握 REST APIを使用して管理できるデータ接続のタイプについて説明するトピックを参照してください。 サポートされるデータ・ソース
JSONペイロード書式の決定 データ・ソースのJSONペイロード書式について説明するトピックを参照し、必要な接続パラメータを取得してください。 データ・ソースのサンプルのJSONペイロード
接続の作成 ワークブック、レポート、ダッシュボードで使用するデータ接続を作成します。 接続の作成(プレビュー)
接続の更新 既存のデータ接続のプロパティを1つ以上更新します。 接続の更新(プレビュー)
接続の削除 データ接続を削除します。 接続の削除(プレビュー)

REST APIを使用してデータ・ソース接続を管理する方法

これらのサンプルおよび例は、cURLを使用したREST APIリクエストによるデータ・ソース接続の管理に役立ちます。

cURL書式の例

次に示すcURLのコマンド書式を使用して、REST APIでデータ・ソース接続を作成または更新します:
  • 単純なJSON
    curl 
    --header "Authorization: Bearer <token>" 
    --header "Content-Type: application/json" 
    --request POST|PUT https://<hostname>/api/20210901/catalog/connections
    --data "<data source connection payload>"
  • Multi-part/Form data
    curl 
    --header "Authorization: Bearer <token>" 
    --request POST|PUT https://<hostname>/api/20210901/catalog/connections
    --form "cert=<security wallet file>"
    --form "connectionParams=<data source connection payload>"
ここで:
  • <token> - Oracle Analytics CloudのREST APIに対するコールの認証に必要なOAuth 2.0 bearerトークン。OAuth 2.0トークン認証を参照してください。

  • <hostname> - Oracle Analytics Cloudが実行されているホスト。

  • <data source connection payload> - データ・ソース固有の接続情報。データ・ソースのサンプルのJSONペイロードを参照してください。

  • <security wallet file> - 認証と署名資格証明、秘密キー、証明書、信頼できる証明書など、SSL関連の情報が格納されます。Oracle Database (SSL)やOracle Autonomous Data Warehouse (相互TLS)など、一部の接続タイプに必要です。

次の例では、Oracle Autonomous Data Warehouse (ADW)への接続の作成方法を示します。

  • 例1 - Oracle ADWへのウォレットなし(TLS)の接続の作成
  • 例2 - 資格証明ウォレット・ファイルcwallet.sso (相互TLS)を使用するOracle ADWへの接続の作成

Oracle Analytics Cloud REST APIには、この他の例が掲載されています。「接続の作成(プレビュー)」、「接続の更新(プレビュー)」、および「接続の削除(プレビュー)」を参照してください。

注:

後続の例にあるJSONペイロードは、Oracle ADWに固有のものです。その他のデータ・ソースでは、JSONペイロードの書式は異なります。サポートされるデータ・ソースのサンプルのJSONペイロードを参照してください。

例1 Oracle ADWへのウォレットなし(TLS)の接続の作成

この例では、oracle_adw_walletlessという名前の接続を作成します。リクエスト本文には、単純なJSONのapplication/jsonが含まれます。
curl 
  --header "Authorization: Bearer <token>"
  --header "Content-Type: application/json" 
  --request POST https://example.com/api/20210901/catalog/connections 
  --data "{
     "version": "2.0.0",
     "type": "connection",
     "name": "oracle_adw_walletless",
     "description": "Sample Oracle ADW connection without a wallet created using Connections API",
     "content": {    
       "connectionParams": {
           "connectionType": "oracle-autonomous-data-warehouse",
           "connectionString": "(description= (retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1521)(host=adb.us-ashburn-1.oraclecloud.com))(connect_data=(service_name=abcdefg1hijkl2m_adwwalletless_high.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)))",
           "username": "ADMIN",
           "password": "<<password>>",
           "systemConnection": false,        
           "remoteData": false,
           "sslType": "ServerSideSSL"
       }
     }
   }"

レスポンス本文

{"connectionID":"J0FkbWluJy4nb3JhY2xlX2Fkd193YWxsZXRsZXNzJw=="}

Base64でエンコードされている、レスポンス本文のconnectionIdをメモします。後から、この値を使用して、接続の更新や削除を実行できます。

例2 ウォレット・ファイル(相互TLS)を使用するOracle ADWへの接続の作成

この例では、oracle_adw_with_walletという名前の接続を作成します。リクエスト本文には、multipart/form-dataが含まれているため、Oracle ADWのウォレット・ファイル(cwallet.sso)とOracle ADW接続パラメータの両方が必要です。
curl
 --header "Authorization: Bearer <token>"
 -–request POST https://<hostname>/api/20210901/catalog/connections 
 --form "cert=@"/Users/scott/Downloads/Wallet_adw/cwallet.sso"" 
 --form "connectionParams= "{
    "version": "2.0.0",
    "type": "connection",
    "name": "oracle_adw_with_wallet",
    "description": "Sample Oracle ADW connection with a wallet created using Connections API",   
    "content": {
      "connectionParams": {
        "connectionType": "oracle-autonomous-data-warehouse",
        "connectionString": "(description= (retry_count=20)(retry_delay=3)(address=(protocol=tcps) (port=1522)(host=adb.us-ashburn-1.oraclecloud.com))(connect_data=(service_name=abcdefg1hijkl2m_walletadw_high.adwc.oraclecloud.com/))(security=(ssl_server_dn_match=yes)))",
        "username": "ADMIN",
        "password": "<<password>>",
        "remoteData": "false",   
        "systemConnection": false,
        "sslType": "ClientSideSSL"    
       }
      }
    }"

レスポンス本文

{"connectionID":"J2FkbWluJy4nb3JhY2xlX2Fkd193aXRoX3dhbGxldCc="}

Base64でエンコードされている、レスポンス本文のconnectionIdをメモします。後から、この値を使用して、接続の更新や削除を実行できます。

データ・ソースのサンプルのJSONペイロード

データ・ソースに接続するには、接続パラメータを指定します。接続REST APIを使用する際は、JSONペイロード書式で接続パラメータを指定します。次の表を利用して、接続するデータ・ソースのJSONペイロードを判断します。

データ・ソース リクエスト・タイプ 入力ペイロード

Oracle Database

(非SSL)

application/json

基本接続タイプ

{ 
 "version": "2.0.0", 
 "type": "connection",  
 "name": "oracle_db_non_ssl_basic",
 "description": "Sample non-SSL Oracle Database connection created using Connections API",
 "content": {
   "connectionParams": {
     "connectionType": "oracle-database",
     "host": "example.com",
     "port": "1521",
     "serviceName": "orcl",
     "username": "admin",
     "password": "<password>",
     "remoteData": false,
     "systemConnection": false
   }
  }
 }

拡張接続タイプ

{
  "version": "2.0.0",
  "type": "connection",
  "name": "oracle_db_non_ssl_advanced ",
  "description": " Sample non-SSL Oracle Database connection created with the advanced connection string format using Connections API",
  "content": {
    "connectionParams": {
     "connectionString": "(DESCRIPTION= (ADDRESS_LIST= (LOAD_BALANCE=on)(FAILOVER=ON) (ADDRESS=(PROTOCOL=tcp)(HOST=example.com)(PORT=1521))) (CONNECT_DATA=(SERVICE_NAME=ORCLPDB1)))",
     "username": "admin",
     "password": "<password>",
     "connectionType": "oracle-database",
     "remoteData": false,
     "systemConnection": false
    }
  }
}

Oracle Database (SSL)

multi-part/form-data
cwallet.sso (client credentials file)

基本接続タイプ

cert: <cwallet.sso file location>
connectionParams: {
 "version": "2.0.0",
 "type": "connection",
 "name": "oracle_db_ssl",
 "description": "Sample Oracle Database connection with SSL created using Connections API",
 "content": {
   "connectionParams": {
     "connectionType": "oracle-database",
     "host": "example.com",
     "port": "2484",
     "serviceName": "ORCLPDB1",
     "username": "admin",
     "password": "<password>",
     "systemConnection": false,
     "remoteData": false
   }
  }
}

Oracle Autonomous Data Warehouse - ウォレットなし(TLS)

application/json

基本接続タイプ

{
 "version": "2.0.0",
 "type": "connection",
 "name": "oracle_adw_walletless_basic",
 "description": "Sample Oracle ADW connection without a wallet created using Connections API",
 "content": {
   "connectionParams": { "connectionType": "oracle-autonomous-data-warehouse",
     "connectionString": "(description= (retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1521) (host=example.com)) (connect_data=(service_name=example.com)) (security=(ssl_server_dn_match=yes)))",
     "username": "admin",
     "password": "<password>",
     "systemConnection": false,
     "remoteData": false,
     "sslType": "ServerSideSSL"
     }
   }
 }

Oracle Autonomous Data Warehouse - ウォレットあり(相互TLS)

multipart/form-data
cwallet.sso (client credentials file)

基本接続タイプ

cert: <cwallet.sso file location>

connectionParams: {
 "version": "2.0.0",
 "type": "connection",
 "name": "oracle_adw_with_wallet",
 "description": "Sample Oracle ADW connection with wallet created using Connections API",
 "content": {
   "connectionParams": {
     "connectionType": "oracle-autonomous-data-warehouse",
     "connectionString": "(description= (retry_count=20)(retry_delay=3)(address=(protocol=tcps)
                        (port=1522)(host=example.com))
                        (connect_data=(service_name=example.com))
                        (security=(ssl_server_dn_match=yes)))",
     "username": "admin",
     "password": "<password>",
     "remoteData": "false",
     "systemConnection": false,
     "sslType": "ClientSideSSL"
    }
  }
 }

PostgreSQL

(非SSL)

application/json

基本接続タイプ

{
 "version":"2.0.0",
 "type": "connection",
 "name": "postgres_non_SSL",
 "description": "Sample PostgreSQL connection created using Connections API",
 "content": {
   "connectionParams": {
     "connectionType": "postgresql-database",
     "host": "example.com",
     "port": "5432",
     "serviceName": "postgres",
     "username": "admin",
     "password": "<password>",
     "remoteData": false,
     "systemConnection": false 
    }
  }
}

PostgreSQL (SSL)

application/json

基本接続タイプ

{
 "version":"2.0.0",
 "type": "connection",
 "name": "postgres_SSL_Conn",
 "description": "Sample PostgreSQL connection with SSL created using Connections API",
 "content": {
   "connectionParams": {
     "connectionType": "postgresql-database",
     "host": "example.com",
     "port": "5432",
     "serviceName": "postgres",
     "username": "admin",
     "password": "<password>",
     "sslType":"ServerSideSSL",
     "remoteData": false,
     "systemConnection": false
    }
  }
}

SQL Server

(非SSL)

application/json

基本接続タイプ

{
 "version":"2.0.0",
 "type": "connection",
 "name": "SqlServer_non_ssl",
 "description": "Sample non-SSL SQL Server connection created using Connections API",
 "content": {
   "connectionParams": {
     "connectionType": "sqlserver-database",
     "host": "example.com",
     "port": "1400",
     "serviceName": "sqlserver1",
     "username": "admin",
     "password": "<password>",
     "remoteData": false,
     "systemConnection": false
    }
  }
}
SQL Server (SSL) application/json

基本接続タイプ

{
 "version":"2.0.0",
 "type": "connection",
 "name": "SqlServer_ssl",
 "description": "Sample SQL Server connection with SSL created using the Connections API",
 "content": {
   "connectionParams": {
     "connectionType": "sqlserver-database",
     "host": "example.com",
     "port": "60190",
     "serviceName": "sqlserver1",
     "username": "admin",
     "password": "<password>",
     "sslType":"ServerSideSSL",
     "remoteData": false,
     "systemConnection": false
    }
  }
}

MySQL

(非SSL)

application/json

基本接続タイプ

{
 "version":"2.0.0",
 "type": "connection",
 "name": "MySql_no_SSL",
 "description": "Sample MySQL connection created using the Connections API",
 "content": {
   "connectionParams": {
     "connectionType": "mysql-database",
     "host": "example.com",
     "port": "3307",
     "serviceName": "mysql1",
     "username": "admin",
     "password": "<password>",
     "remoteData": false,
     "systemConnection": false
    }
 }
}
MySQL (SSL) application/json

基本接続タイプ

{
 "version":"2.0.0",
 "type": "connection",
 "name": "MySql_ssl",
 "description": "Sample MySQL connection with SSL created using Connections API",
 "content": {
   "connectionParams": {
     "connectionType": "mysql-database",
     "host": "example.com",
     "port": "3306",
     "serviceName": "mysql1",
     "username": "admin",
     "password": "<password>",
     "sslType":"ServerSideSSL",
     "remoteData": false,
     "systemConnection": false
    }
  }
}

Oracle Essbase

application/json

基本接続タイプ

{
 "version":"2.0.0",
 "type": "connection",
 "name": "Oracle_Essbase",
 "description": "Sample Oracle Essbase connection created using Connections API",
 "content": {
   "connectionParams": {
     "connectionType": "oracle-essbase",
     "dsn":"example.com",
     "username":"admin",
     "password":"<password>",
     "remoteData": false,
     "systemConnection": false,
     "authentication":"current"/"private"/"sso"
    }
  }
}