クリアフィルター
記事
Hiroshi Sato · 2020年11月16日
これはInterSystems FAQ サイトの記事です。
Config.Configurationクラス、SYS.Databaseクラスのメソッドを使用して、ネームスペース・データベースの作成及び登録をターミナルから実行することができます。
以下はデータベースファル/CacheDB/AAA/cache.datを作成し、構成ファイル(cache.cpf)にデータベース AAA、及び、ネームスペースAAAの登録を行う一連の実行例です。*実行は、%SYSネームスペースで行って下さい。*
Set Directory="/CacheDB/AAA/"Set x=$ZF(-100, "/shell", "mkdir", Directory)Set db=##Class(SYS.Database).%New()Set db.Directory=DirectorySet status=db.%Save()Set DBName="AAA"Set status=##class(Config.Configuration).AddDatabase(DBName,Directory)Set NSName=DBNameSet status=##class(Config.Configuration).AddNamespace(NSName,DBName)
リモートデータベースからネームスペースを作成する場合は、以下のデータベース定義で、第三パラメータにリモートのサーバ名を指定します。
Set status=##class(Config.Configuration).AddDatabase(DBName,Directory,Server)
※クラスの詳細については、それぞれのクラスリファレンスをご参照下さい。
また、データベースの作成・登録については、^DATABASEルーチンを使用することも可能です。
このルーチンを実行すると、下記のようにオプションが表示されますので、目的によって選択します。
以下は、データベース作成の実行例です。*実行は、%SYSネームスペースで行って下さい。*
%SYS>do ^DATABASE 1) Create a database2) Edit a database3) List databases4) Delete a database5) Mount a database6) Dismount a database7) Compact a database8) Show free space for a database9) Show details for a database10) Recreate a database11) Manage database encryptionOption? 1Database directory? D:\200820DS\Mgr\TEST2Directory does not exist, create it? No => yChange default database properties? No =>Dataset name of this database in the configuration: TEST2Mount TEST2 Required At Startup? No => yConfirm creation of database in d:\200820ds\mgr\test2\? Yes => yFormatting...Database in d:\200820ds\mgr\test2\ createdDataset TEST2 added to the current configuration.Database directory?
※^DATABASEルーチンの各オプションについては、以下ドキュメントページをご参照ください。
^DATABASEについて【IRIS】^DATABASEについて
お知らせ
Seisuke Nakahashi · 2025年3月12日
InterSystems はこのたび「テーブル・パーティショニング機能」の早期アクセスプログラムを開始しました。これにより、IRIS をお使いのお客様が非常に大きなテーブルを管理したり、行データや関連インデックスをデータベースやストレージ階層間で分散できるようになります。テーブル・パーティショニングは IRIS のリレーショナル・データ管理の核心深くに関連する機能であるため、初期段階でのフィードバックを提供いただけたり、状況に応じて機能調整にご協力いただける、少数の熱心なお客様と一緒になって、確実な機能実装を進めたいと考えています。
非常に大規模なリレーショナル・データセットをご利用中で、より効率的な運用を望まれており、新機能を試してみたいというお客様は、ぜひ https://www.intersystems.com/early-access-program/ からご登録ください。登録された方には、一時的な開発ライセンス、新機能を含む最新キットとコンテナ・イメージ、チュートリアル がすべて掲載された評価ポータルをご案内するメールをお送りします。
登録された参加者のみなさまには、関連するアップデートがリリースされるたびにご連絡を差し上げます。もちろん、ご要望がございましたら、みなさまのテストを直接お手伝いさせていただくことも可能です。早期アクセスプログラムへのご登録を心よりお待ちしております。
記事
Shintaro Kaminaka · 2020年9月4日
開発者の皆さん、こんにちは。
今回の記事ではFHIRと組み合わせて使用されるケースが増えてきている、権限の認可(Authorization)を行うためのOAuth2について取り上げます。
まずこのパート1では、IRIS for HealthおよびApacheのDockerコンテナの起動と、IRIS for Health上で、OAuth2認可サーバ機能を構成し、REST開発ツールPostmanからアクセスし、アクセストークンを取得する方法について解説します。さらにパート2以降では、IRIS for HealthにFHIRリポジトリ機能を追加し、OAuth2リソースサーバ構成を追加して、Postmanからアクセストークンを使用したFHIRリクエストの実行方法まで解説します。
InterSystems製品のOAuth2機能の解説については、すでにいくつかの記事が開発者コミュニティ上に公開されていますが、今回は改めて最新バージョンでの構成方法を解説したいと思います。InterSystems IRIS Open Authorization Framework(OAuth 2.0)の実装 - パート1
今回の記事では、最新のInterSystems IRIS for Health 2020.3 Preview Editionを使用します。実際にこの記事を元にして、環境を構築してみようと思われた方は必ずこのバージョン以降のキットを使用してください。一部機能がこのバージョン以前の製品には含まれていません。
事前準備
まずは事前準備です。セキュアな環境を構築するために、色々と準備することが多いです。
IRIS for Health 2020.3 Preview EditionはDockerコンテナバージョンだけが提供されています。(InterSystems Docker Hub/IRIS for Health)また、OAuth2構成を行うためには、WebサーバおよびSSL構成を行う必要があります。今回はApacheを使用します。Apache上でSSL構成を行う場合、SSL構成の証明書は正しくサーバのホスト名と一致している必要があります。この点を注意してください。
intersystems-jp GitHub リポジトリからのサンプルファイルの取得
インターシステムズ開発者コミュニティ専用のGitHubリポジトリに今回の構成で使用するサンプルの docker-compose.yml/Dockerfile等が公開されています。まずは以下のコマンドでご利用の環境にこのファイルを展開してください。(この記事の添付ファイルにも追加されているのでそちらからでもOKです。)このdocker-compose.yml/Dockerfile等のファイルは、OpenExchangeに公開されているiris-webgateway-exampleアプリケーションを参考に作成しています。
git clone https://github.com/Intersystems-jp/IRIS4H-OAuth2-handson.git
使用するキットに合わせた構成の変更
このdocker-compose.ymlファイルでは、IRIS for Healthのコンテナと、docker buildコマンドでbuildされるApache(httpd)のコンテナの二つが起動するように構成されています。GitHubで配布しているdocker-compose.ymlファイルでは、IRIS for Health Community Edition Preview Edition(2020.3.200.0) を指定しています。Community Editionはインターシステムズ製品の評価のために利用していただくことができます。
iris:
image: store/intersystems/irishealth-community:2020.3.0.200.0
異なるバージョン(正式リリースバージョンやより新しいバージョン)を使用する場合は、この部分の指定を変更してください。
Apacheの方のコンテナはDockerfileの内容でbuildされますが、その際にApacheからIRISに接続するためのWebGatewayのキットが必要になります。キットの入手方法についてはインターシステムズパートナーの方々はWRCのキットダウンロードサイトするか、またはWRCサポートセンターへお問い合わせください。それ以外の方々はお手数ですが、こちらのアドレスまでお問い合わせください。
入手した製品に合わせてDockerfileの以下の箇所を変更します。ホストマシンのOSがWindows/Ubuntu/CentOSいずれであっても、ベースとなるhttpdのコンテナOSがDebianであるため、platformはlnxubuntux64の指定となります。
ARG version=2020.3.0.200.0
ARG platform=lnxubuntux64
ADD WebGateway-${version}-${platform}.tar.gz /tmp/
SSL証明書の用意
次にSSL証明書を用意します。OAuth2 認可アクセス時には、そのWebサーバで設定されているSSL証明書がアクセスしているURLと一致しているか確認を行います。公式な証明書でなくても、openssl等を使用した証明書作成で問題はありません。証明書作成時にCommon Nameにホスト名を入力してください。
また、作成した証明書は起動時に自動で読み込むため、パスフレーズが不要なファイルに変更しておく必要があります。以下のコマンドを参考にしてください。
$ openssl rsa -in cert.key.org -out cert.key
作成された CRTファイルおよび、KEYファイルをそれぞれ server.crt / server.key というファイル名で、Dockerfileと同じディレクトリにおいてください。
また、Apache Webサーバで利用する以外にも、OAuth2の設定でSSL証明書が必要になります。これらはホスト名の入力等は必要がありませんが、3セット作成しておいてください。(以降の設定ではauth.cer/auth.key , client.cer/client.key , resserver.cer/resserver.key として登場します。 )
dockerビルド と dockerコンテナの起動
これでようやく準備完了です!今ディレクトリには、DLした4つのファイル以外に、Webゲートウェイのインストールキット、そして二つのSSL証明書がある状態です。各ファイルのアクセス・実行権限等にもご注意ください。(例えば私は、webgateway-entrypoint.shに実行許可を追加しました。)
docker-compose build
docker-compose up -d
起動したら、docker ps コマンドで二つのコンテナが起動していることを確認します。
ApacheのコンテナIMAGE名:<directoryname>_web
IRIS for Healthのコンテナ:store/intersystems/irishealth-community:2020.3.0.200.0(あるいはそれぞれ指定したIMAGE)
次は、以下の3つの方法で管理ポータルにアクセスしてみてください。最後の3番目の方法でうまくアクセスできれば、Apache Webサーバ経由のSSL構成は成功です!
http://<hostname>:52773/csp/sys/UtilHome.csp : このURLはIRIS コンテナのPrivate Apache経由のアクセスです。構成したApacheは経由しません。
http://<hostname>/csp/sys/UtilHome.csp : このURLは構成したApacheを経由して管理ポータルにアクセスしています。
https://<hostname>/csp/sys/UtilHome.csp : このURLは構成したApache経由でSSL接続を使用して管理ポータルにアクセスしています。
SSL構成の作成
それでは、IRIS for Healthが起動し、管理ポータルにアクセスできるようになったので、最後の準備としてSSL構成を作成しましょう。
管理ポータル→システム管理→セキュリティ→SSL/TLS構成 と進み、先ほど作成した3ペアの証明書キーを使って、SSLの構成を3つ作成しておいてください。
名前は自由に決めることができますが、この記事では過去のOAuth2関連記事にならって、SSL4AUTH/SSL4CLIENT/SSL4RESSERVER としています。
*ホストとコンテナのディレクトリ共有について
docker-composeファイルに記載されている以下のvolumes 指定によって、ホストの現在のディレクトリ位置=コンテナ内の /ISC ディレクトリ となっています。上記の設定等で証明書ファイルを指定する場合は、このディレクトリを活用してください。
volumes: - .:/ISC
このディレクトリには、ファイルだけでなくIRISのデータベースファイルや構成ファイルも配置されます。詳しくはドキュメント「永続インスタンス・データを保存するための永続的な %SYS」をご覧ください。
IRIS for HealthでOAuth2の構成
いよいよIRIS for HealthにOAuth2を使ってアクセスするための具体的な準備に入ります!
OAuth2認可サーバ構成
まずはOAuth2認可サーバの構成です!管理ポータル→システム管理→セキュリティ→OAuth 2.0→サーバ と進みます。
以下の内容に従って設定します。
「一般」タブ設定内容
発行者エンドポイント:ホスト名
<実際のホスト名を入力します>
:プレフィックス
任意の値を入力できますが、ここでは「authserver」としています。
サポートする許可タイプ
この記事の中では認証コード(Authorization Code)しか使用しませんが、他の許可タイプ(Grant Type)もテストしてみたい方はチェックを追加してください。また、「JWT承認」にもチェックを追加します。
SSL/TLS構成
先ほど追加したSSL構成を指定します。
「スコープタブ」では、「サポートしているスコープを追加」をクリックして追加します。あとで、表示される認可コード(Authorization Code)のログイン画面ではここで記述した「説明」が表示されます。
「間隔」タブはデフォルトから変更する内容はありません。「JWT」タブでは署名アルゴリズムに「RS512」を選択してみましょう。
最後の「カスタマイズ」タブでは、トークン・クラスを生成 の指定を %OAuth2.Server.JWT に変更します。
入力したら、「保存」ボタンを押して、構成を保存します。
これで、IRIS for HealthがOAuth2認可サーバとして稼働する基本の設定ができました。早速Postmanからアクセスしてアクセストークンが取得できるか試してみましょう!
しかし、その前にあと2つ構成を行わなければいけません。
クライアントデスクリプションを追加する
まずはOAuth2クライアントとしてアクセスするPOSTMANの情報を追加します。OAuth2クライアント登録は動的登録などで追加されることもあります。
サーバ構成画面の「クライアントデスクリプション」をクリックして先に進みます。
「クライアントデスクリプションを作成」をクリックしてエントリを追加します。
以下の内容に従ってクライアントデスクリプションを作成します。
「一般」タブ設定内容
名前
任意の名前を入力します。ここでは postmanとしました。
クライアントの種別
「機密」を選択します。
リダイレクトURL
「URLを追加」ボタンから追加します。postmanのリダイレクトURLとしてhttps://www.getpostman.com/oauth2/callbackを指定します。
サポートする許可タイプ
OAuth2認可サーバの設定で構成した内容と同じ「認証コード」(Authorization Code) を指定します。(デフォルト)他の許可タイプもテストしてみたい場合はチェックを追加します。ただし、認可サーバの構成と同じ設定にする必要があります。また、「JWT承認」にもチェックを入れます。ただし、ここで指定する
認証署名アルゴリズム
サポートする許可タイプで「JWT承認」をチェックすると、選択できるようになります。「RS512」を選択します。
入力できたら「保存」ボタンを押してクライアントデスクリプションを保存します。
「クライアント認証情報」タブをクリックすると、このエントリに対するクライアントIDとクライアントの秘密鍵を確認することができます。POSTMANからテストするときはこのIDと秘密鍵が必要になります。
ウェブアプリケーションの追加
POSTMANからアクセスする前にもう一つ大事な設定を加える必要があります。OAuth2認可サーバ構成画面で、この構成のエンドポイントが https://<hostname>/authserver/oauth2 と決定されました。このエンドポイントへのアクセスが正しくIRISで処理されるために、このURLパスに対するウェブアプリケーションの追加を行う必要があります。
システム管理→セキュリティ→アプリケーション→ウェブ・アプリケーション と進み、「新しいウェブ・アプリケーションを作成」をクリックします。
OAuth2のウェブ・アプリケーションのテンプレートが用意されているので、まず「コピー元」から「/oauth2」を選択します。
「ウェブ・アプリケーションの編集」設定項目
コピー元
/oauth2 プルダウンから必ずこちらを先に選択します。
名前
/authserver/oauth2
有効
「REST」のラジオボタンをチェックします。
各値を入力したら保存します。
POSTMANからOAuth2のテストを行う
それではPOSTMANからテストしてみましょう。テストの実行は他のツールや実際のプログラムから行うこともできます。POSTMANの詳しい説明はこの記事では触れませんが、一点注意点として、POSTMANのSettingでSSL certificate verificationはOFFに変更するようにしてください。
POSTMANで新しいリクエストを作成後、AuthorizationタブのTYPEで「OAuth 2.0」を選択し、「Get New Access Token」をクリックします。
次の画面で、以下の内容に従って値を入力していきます。
「GET NEW ACCESS TOKEN」設定項目
Token Name
任意の名前を入力します。
Grant Type
「Authorization Code」を指定します。
Callback URL
https://www.getpostman.com/oauth2/callback
Auth URL
https://<hostname>/authserver/oauth2/authorize?ui_locales=jaエンドポイント+/authorize の値を入力します。ui_locales=ja を追加することで日本語のログイン画面を表示させることができます。
Auth Token URL
https://<hostname>/authserver/oauth2/tokenエンドポイント+/token の値を入力します。
Client ID
クライアントデスクリプションの登録後にクライアント認証情報タブに表示される クライアントID を入力します。
Client Secret
クライアントデスクリプションの登録後にクライアント認証情報タブに表示される クライアントの秘密鍵 を入力します。
Scope
認可サーバ構成で登録したスコープを入力します。 scope1 など。スペースで区切って複数指定することもできます。
State
CSRF対策などで使用されるStateパラメータを入力します。特に使用しませんが空白にできないので、任意の文字列を入力しています。
パラメータ入力後、「Request Token」ボタンを押すと、以下のようなログイン画面が表示されたでしょうか?
管理ポータルにアクセスしているユーザ情報 (_SYSTEM等) でログインしてみてください。
ログイン後の次の画面では、このアプリケーションに権限の許可を与えるかどうか決定できます。「許可」をクリックしたあと、次の画面で以下のようにAccess Tokenが表示されれば、アクセストークン取得テストは成功です!
OpenID Connectのテスト
IRIS for Healthでは、OAuth2の認可処理だけでなく、OpenID Connectに準拠した認証処理を実施することができます。詳細はこちらのドキュメントを参照してください。
今回の構成では実はOpenID Connectの設定も有効になっています。OpenID ConnectののIDトークンも取得できるかテストしてみましょう!
やり方は簡単です。先ほどのGET NEW ACCESS TOKEN画面で、Scopeに「openid」を追加してリクエストしてみましょう。
権限の要求ページでも、OpenID Connectが表記されます。ログイン処理を行い、許可を与えた後に次の画面が表示されたらIDトークン(id_token)も取得できることを確認してください。(画面を下にスクロールする必要があります。)
いかがでしたか?Access Token そして id_tokenが取得できたでしょうか?
証明書等、少々手間がかかる準備もありますが、データベースプラットフォームであるIRIS for Health上でもこれだけ簡単にOAuth2認可サーバを構築することができました。
この連載の次のパートでは、いよいよFHIRリポジトリを構築し、FHIRリポジトリのOAuth2リソースサーバ登録、そして再びPOSTMANからOAuth2アクセストークンを使用したFHIRリポジトリへRESTアクセスする方法を紹介していきます。 記事を参考にしてアクセストークンの取得まで試してみたところ問題なく動作しました。
有益な記事をアップして頂きありがとうございます。
以下、記載されている手順以外で実行したものを列挙させて頂きます。
他に試す方のご参考になれば幸いです。
**SSL証明書の用意**
Apache Webサーバー用のSSL証明書を作成
```
openssl genrsa 2048 > server.key
openssl req -new -key server.key > server.csr
→ CommonNameにDockerホストのホスト名を指定
openssl x509 -days 100 -req -signkey server.key < server.csr > server.crt
```
OAuth2.0用のSSL証明書を作成
```
openssl genrsa 2048 > auth.key
openssl x509 -days 100 -req -key auth.key -out auth.cer
```
**dockerビルド と dockerコンテナの起動**
Dockerfileの38行目に以下を追加し、権限を設定
```
RUN chmod +x /opt/webgateway/bin/webgateway-entrypoint.sh
```
**POSTMANからOAuth2のテストを行う**
自己署名証明書のためPostmanで「self signed certificate」エラーが発生するため、
設定から「SSL certificate verification」をOFFに設定。
記事
Mihoko Iijima · 2025年6月24日
これは InterSystems FAQ サイトの記事です。
InterSystems 製品インストール時に用意されている事前定義ロールを利用して、ログインユーザ毎に管理ポータルメニュー(システム管理/システムエクスプローラー/システムオペレーション など)のアクセスを制限することができます。
管理ポータルメニューに対するアクセス制限を行うためには、管理ポータルへの「認証なし(UnknownUser)」アクセス(※1)を使用しない環境が必要です。
管理ポータル上部の「ログアウト」をクリックしてログイン画面が表示されない場合は、関連記事「管理ポータル/スタジオ/ターミナルにパスワード認証を設定するにはどうしたらいいですか?」をご覧いただき必要な設定を行ってください。
以下、インストールデフォルトで管理ポータルへのフルアクセスが許可されている事前定義ユーザ(※2): SuperUser や _SYSTEM アカウントを使用して管理ポータルにログインした状態の設定例でご説明します。
これらユーザのパスワードはインストール時に設定しています(インストール時の「初期セキュリティ」を「最小」でインストールした環境では、パスワードは大文字の SYS が設定されています)。
InterSystems 製品はロールベースのセキュリティを使用しています。ログインユーザ毎にアクセスできるメニューを制限したい場合は、付与するロールを変えることで実現できます。
InterSystems 製品内でロールとは「特権の集まり」に名前を付けたもので、「特権」は「リソース(=保護対象全般)に対する許可(READ/WRITE/USE)」を組み合わせた定義です。必要な特権を定義したロールを作成しユーザに付与することで細かなアクセス制御をユーザに対して定義できます。
言葉の定義や内容詳細については関連記事:「InterSystems 製品のセキュリティの基本:ユーザとロール」でご説明しています。ぜひご参照ください。
※1 InterSystems IRIS をインストールする際の指定で「初期セキュリティ」を「最小」とした場合に設定されるアクセスです。InterSystems IRIS for Healthでは、「初期セキュリティ」オプションは「通常」以上の設定となるため、デフォルトで「認証なし」アクセスを使用しないように設定されます。
※2 %All ロールを持つユーザです。
ここでは、以下の事前定義ロールを付与したユーザを作成し、管理ポータルログイン後の表示の違いを確認してみます。
1) %Manager ロール
システム管理に関連付けられた特権を持つロールです。管理ポータルの「システム管理」「システムエクスプローラ」「システムオペレーション」にアクセスできます。
例では、TestA ユーザにこのロールを付与します。
2) %Developer ロール
アプリケーション開発に関連付けられる特権を持つロールです。このロールでは開発者に必要なターミナルアクセスと、管理ポータルの「システムエクスプローラ」にアクセスできます。
例では、TestB ユーザにこのロールを付与します。
3) %Operator ロール
システム運用メニューに関連付けられた特権を持つロールです。管理ポータルの「システムオペレーション」にアクセスできます。
例では、TestC ユーザにこのロールを付与します。
管理ポータルの「Interoperability」メニュー については、Interoperability メニュー以下を操作する方の役割に合わせた事前定義ロールが細かく分かれています。
詳細はドキュメント「プロダクション関連の事前定義ロール」をご参照ください。
また、Interoperabilityメニューを利用する場合は、管理ポータル用ロールの他に、アクセス対象のデータベース用ロール(%DB_XXXX)も必要となります。
IRIS for Health をインストールすると表示される「Health」メニューについては、%HS_Administrator ロール と 操作対象のデーベース用ロール(%DB_XXXX)が必要です。
それでは早速、異なるロールを付与されたユーザ別の管理ポータルログイン後の表示の違いを確認します。
1) %Manager ロールを付与した TestA での表示
2) %Developer ロールを付与した TestB での表示
3) %Operator ロールを付与した TestC での表示
1) %Managerロールを付与した TestA での表示
以下の手順でTestAユーザを作成し、確認します。
手順1:TestA ユーザを作成し、%Managerロールを付与
手順2:管理ポータルにログインしてテスト
手順1:TestA ユーザを作成し、%Managerロールを付与
TestA を作成します。パスワード(3文字以上の大小文字を区別する英数字)を設定し、保存します。保存後、ロールタブで%Manager ロールを付与します。
手順2:管理ポータルにログインしてテスト
では、テストしてみます。
管理ポータルをログアウトした後で、TestA でログインします。ログイン後の見栄えは以下の通りです。
2) %Developer ロールを付与した TestB での表示
以下の手順でTestBユーザを作成し、確認します。開発者用ロールであるため、テストでは管理ポータルの他にターミナルからのアクセスも試します。また、管理ポータルからの SQL の実行も試してみます。
手順0:現在の管理ポータルをログアウトとし管理者ユーザでログイン
手順1:TestB ユーザを作成し、%Developer ロールとデータベース用ロールを付与
手順2:管理ポータルにログインして表示を確認
手順3:ターミナル(またはIRIS)へのログインテスト
手順4:管理ポータルのSQLメニューでSQLの実行テスト
手順0:現在の管理ポータルをログアウトとし管理者ユーザでログイン
TestB を作成するため、管理者ユーザ(SuperUserや_SYSTEM) でログインし直します。
手順1:TestB ユーザを作成し、%Developer ロールとデータベース用ロールを付与
作成するTestB ユーザには %Developer ロールを付与するため、管理ポータルの「システムエクスプローラ」を利用できます。
「システムエクスプローラ」はグローバル変数の参照や、クラス定義・ルーチンのインポートエクスポート、さらに SQL の実行などが行える開発者向けメニューとなるため、%Developer ロールの他にデータベース用ロールが必要となります。
データベース作成時のセキュリティ設定次第となりますが、デフォルトを選択している場合は、%DB_%DEFAULT ロールを付与します。
データベースリソースを作成している場合は、データベース用ロールを付与します。例では、USER データベース用ロール:%DB_USER を付与しています。
手順2:管理ポータルにログインして表示を確認
TestB ユーザでログインを行うと、システムエクスプローラーが選択できるように見えます。
ですが、「システムエクスプローラー」を選択してもほとんどのメニューが利用できません。
これは、管理ポータルにログインしたときのネームスペースが %SYS になっているからです。
TestB ユーザの設定にある「開始ネームスペース」に USER を指定するか、管理ポータルを開いた後ネームスペースを USER に切り替えることでサブメニューを操作できるようになります。
まずは、ネームスペースを切り替えてみます。
以下の画面は、TestB の「開始ネームスペース」に USER を設定したときの図です。
手順3:ターミナル(またはIRIS)へのログインテスト
%Developer ロールは開発者用ロールでターミナルや IRIS にログインすることができます。試しに、IRIS にログインしグローバル変数を作成してみます。
irisowner@1fed473da3f3:/opt/src$ iris session iris
ノード: 1fed473da3f3 インスタンス: IRIS
ユーザ名:TestB
パスワード:*****
USER>
USER>
USER>set ^ABC=1
USER>write ^ABC
1
ログインも、グローバルの更新も参照もできました。管理ポータルからも参照できるか確認します。
無事参照できています。
手順4:管理ポータルのSQLメニューでSQLの実行テスト
続いて、SQL画面にアクセスし、テーブルを作成してみます。
エラーが出てしまいました。
SQL 画面については、テーブルの操作に対する権限も含めてユーザに付与する必要があります。
TestB ユーザにテーブルに対する権限を追加します。これには、SuperUser でログインし直してから USER ネームスペースに対して CREATE TABLE が利用できる権限を追加します。
では、TestB ユーザにログインしなおして試してみます。
テーブルの作成とデータ登録を行ってみます。
無事、テーブル作成も INSERT 文も実行できました。
ここで、SuperUser でログインしなおし管理ポータルで TestB ユーザの情報を参照すると TestB はテーブル所有者であるため、作成したテーブルに対する SQL テーブル権限が付与されています。
所有者ではないテーブルに対しては、テーブル毎にテーブル権限を付与する必要がありますのでご注意ください。
また例では、SQL の特権を TestB ユーザに直接付与しましたが、専用ロールを作成しロールをユーザに付与する方法でも定義できます。
他のユーザに同じ SQL 特権を付与する場合は、ロールを作成したほうが便利です。
ご参考:ロールに SQL 特権を設定する例
2) %Operator ロールを付与した TestC での表示
最後に、%Operator ロールを持つ TestC を作成します。運用管理に使用するツールはターミナル(またはIRIS)へログインして実行するルーチンなどもあるため、ターミナル(またはIRIS)へのログインも試してみます。
手順0:現在の管理ポータルをログアウトとし管理者ユーザでログイン
手順1:TestC ユーザを作成し、%Operator ロールとデータベース用ロールを付与
手順2:管理ポータルにログインしてテスト
手順3:ターミナル(またはIRIS)へのログインテスト
手順4:ターミナルへのログイン失敗の原因を探る
手順0:現在の管理ポータルをログアウトとし管理者ユーザでログイン
TestC を作成するため、管理者ユーザ(SuperUserや_SYSTEM) でログインし直します。
手順1:TestC ユーザを作成し、%Operator ロールを付与
SuperUser でログインしなおして TestCを作成し、%Operatorロールを付与します。
手順2:管理ポータルにログインしてテスト
以下、TestC でログインした状態です。システムオペレーションメニューが操作できます。
手順3:ターミナル(またはIRIS)へのログインテスト
IRISに TestC ユーザでログインしてみます。
irisowner@1fed473da3f3:/opt/src$ iris session iris
ノード: 1fed473da3f3 インスタンス: IRIS
ユーザ名:TestC
パスワード:*****
アクセスが拒否されました。
TestC はアクセスが拒否されています。
これは、IRIS にログイン(Windows ならターミナルにアクセス)の許可が足りないためです。
手順4:ターミナルへのログイン失敗の原因を探る
手順3でログイン失敗の原因を探るため、一旦管理ポータルをログアウトしSuperUser でログインしなおした後、監査イベントを確認します。
システム管理 > セキュリティ > 監査 > 監査データベースの閲覧 >(検索ボタン押下後) 対象のイベントの「詳細」をクリック
エラーメッセージ: エラー #836: プログラマーアクセスの権限が不十分です
サービス名: %Service_Terminal
上記エラーが出ています。
IRIS にログイン(またはターミナルを起動)するためには、%Service_Terminal(Linux用) または %Service_Console(Windows用) サービスに対する USE 許可、アクセス対象データベースリソース(例では%DB_USER)の READ 許可、そしてプログラマーアクセスの権限として、%Development リソースのUSE許可が必要となります。
TestB ユーザに付与した %Deleveloper ロールはこれらの許可が含まれているため IRIS にログインできていました。
TestC ユーザがどの許可を持っているか?については、プロファイル画面を見ると分かりやすいです。
SuperUserでログインし、システム管理 > セキュリティ > TestCユーザの「プロファイル」をクリックします。
参照しているユーザが利用できるリソースとその許可が一覧されます。
それぞれの許可を確認します(以下の例は Linux 上 IRIS で確認しているため、%Service_Console は表示されていません)。
%DB_USER リソースと、%Development リソースに対する適切な許可が足りていません。
TestC ユーザに %DB_USER リソースの READ/WRITE 許可を持つ %DB_USER ロールと、%Development リソースの USE 許可が含まれる %Developer ロールを付与することで IRIS にログインできます。
irisowner@1fed473da3f3:/opt/src$ iris session iris
ノード: 1fed473da3f3 インスタンス: IRIS
ユーザ名:testC
パスワード:*****
USER>write $roles //このユーザがログインしたときに持っているロールを確認
%Developer,%DB_USER,%Operator
なお、例のようなロール付与以外にもリソースに対してパブリックに許可を設定することでユーザに許可を与えることもできます。プロファイル画面では「パブリックリソースにより付与」の列に情報が記載されています。
ここまでの流れで、事前定義ロールを利用した管理ポータルのアクセス制御が確認できました。
別の記事では、事前定義ロールだけでは対応できない、サブメニューに対するアクセス制御の例をご紹介しています。ぜひご参照ください。
記事
Mihoko Iijima · 2022年1月6日
開発者のみなさん、あけましておめでとうございます🎍 今年もどうぞよろしくお願いします!
さて、この記事では、IRIS ターミナルに(こっそり)追加された便利機能をご紹介します!(つい最近知りまして、びっくりしました)
2023/4/13 追記:Pythonシェルへ切り替えるメソッドのショートカットが追加されていたので返信欄に追記しました。
IRIS ターミナルで以前実行したコマンドを再実行する場合、上矢印キーを連打しながらコマンドを探されていると思うのですが、IRIS 2021.1 から履歴表示と、履歴番号を指定した実行ができるようになっていました!
では早速、履歴(history)の使い方をご紹介します。これがあれば、もう、上矢印キーを連打せずに以前実行したコマンドを再実行できます!!
まずは、履歴を作るため、いくつかコマンドを実行します。
ユーザ名:_system
パスワード:***
USER>
USER>write $ZDATE($NOW(),16)
2022年1月6日
USER>
USER>write $ZV
IRIS for Windows (x86-64) 2021.1 (Build 215U) Wed Jun 9 2021 09:39:22 EDT
USER>
USER>write $system.Util.ManagerDirectory()
c:\intersystems\irishealth\mgr\
USER>
ここで、:? と入力してみます。
(なんと、オプションが表示されます!!)
USER>:?
:<number> Recall command # <number>
:? Display help
:alias Create/display aliases
:clear Clear history buffer
:history Display command history
:unalias Remove aliases
:history (または :h)を実行すると、履歴が表示されます!
USER>:history
1: _system
2: write $ZDATE($NOW(),16)
3: write $ZV
4: write $system.Util.ManagerDirectory()
5: :?
6: :history
コロン(:)と履歴番号を指定し、以前実行したコマンドを再実行してみます。(:4 と入力しています。)
USER>:4
write $system.Util.ManagerDirectory()
c:\intersystems\irishealth\mgr\
USER>
上矢印キーを連打せずに、過去のコマンドを実行できました!便利です
続いて、alias オプションを使うとコマンドのショートカットが作成できるようですので、それも試してみます。
以下の実行例では、TESTネームスペースに移動した後、IRIS ターミナルをSQL実行モードに変更し、SQLを実行しています。
USER>set $namespace="test"
TEST>do $system.SQL.Shell()
SQL Command Line Shell
----------------------------------------------------
The command prefix is currently set to: <<nothing>>.
Enter <command>, 'q' to quit, '?' for help.
[SQL]TEST>>select * from Training.Person
1. select * from Training.Person
ID Email Name
1 yamada@majorcorp.com 山田たろう
1 Rows(s) Affected
statement prepare time(s)/globals/cmds/disk: 0.0462s/3307/171368/2ms
execute time(s)/globals/cmds/disk: 0.0002s/2/675/0ms
cached query class: %sqlcq.TEST.cls166
---------------------------------------------------------------------------
[SQL]TEST>>quit
TEST>
なかなか覚えにくいコマンドに対して、alias を設定しておくと便利そうですので、ターミナルを SQL の実行環境に変更する do $system.SQL.Shell() を設定してみます。
設定方法は以下の通りです。
:alias 名称 コマンド
$system.SQL.Shell() を sqlmode の名称で alias に設定する例は以下の通りです。
TEST>:alias sqlmode do $system.SQL.Shell()
TEST>:alias
sqlmode do $system.SQL.Shell()
早速、設定した alias を使ってみましょう!
TEST>:sqlmode
do $system.SQL.Shell()
SQL Command Line Shell
----------------------------------------------------
The command prefix is currently set to: <<nothing>>.
Enter <command>, 'q' to quit, '?' for help.
[SQL]TEST>>quit
TEST>
無事、実行できました!
(alias 名は省略できるので、上記登録の場合 :s でも実行できるようでした。)
メモ:2021.2プレビュー版では、do $system.SQL.Shell() が alias 名 sql で事前に登録されているため、:sql で SQL 実行モードに切り替えできました。
履歴(history)や alias の例については、ドキュメントにも記載がありますので、併せてご参照ください!
前のコマンドの繰り返し いつの間にか、:py も追加されていました。(Pythonシェルへ切り替わります。)
USER>:py
Python 3.9.5 (default, Jan 13 2023, 15:20:22) [MSC v.1927 64 bit (AMD64)] on win32
Type quit() or Ctrl-D to exit this shell.
>>> import datetime
>>> datetime.datetime.now()
datetime.datetime(2023, 4, 13, 11, 16, 43, 487481)
>>>
もちろん、以下メソッドの実行でも切り替わります。
do ##class(%SYS.Python).Shell()
記事
Mihoko Iijima · 2024年7月7日
これは InterSystems FAQ サイトの記事です。
監査ログはシステムDB内テーブル(%SYS.Audit)に記録されていますので、そのテーブルに対するクエリを実行して抽出したり、%SYS.Auditテーブルに用意されていストアドプロシージャを利用して情報を取得しファイル出力するようにプログラムを用意することもできます。
以下にご紹介する内容は「監査ログをプログラムで出力(ユーザやイベント指定など)する方法」に関連した内容で、監査ログのファイル出力を管理ポータルの機能を利用した例とプログラムを利用した例でご紹介します。
1. 管理ポータルの印刷機能を使う
管理ポータル > [システムエクスプローラ] > [SQL]を開き、%SYSネームスペースに接続します。
システムのチェックを入れ、スキーマに%SYSを指定した後、プロシージャの階層を展開するとプロシージャリストが参照できます。
%SYS.Audit_ で始まるプロシージャが監査ログに対して実行できるプロシージャです。
SQL文例)InterSystems製品内ユーザのSuperUserに対する監査ログをストアドプロシージャ:%SYS,Audit_ListByUser を利用して出力しています。
call %SYS.Audit_ListByUser(,,,,,'SuperUser')
引数については、クラスリファレンス:%SYS.Audit_ListByUserをご参照ください。
管理ポータル内の「印刷」の機能を利用するとファイル出力できます。
2. プログラムでファイル出力する
%SYS上に以下のようなメソッド(またはルーチン)を用意すると任意のカラムのみを出力できます。
注意:クラスの場合はパッケージ名の先頭文字にZを、ルーチンの場合はルーチン名の先頭にZをつけて保存してください。
%SYS.AuditクラスのListByUserプロシージャはクラスクエリとしても実行できるため、コード例ではクラスクエリで実行しています。
また出力するカラムもTimeStampとEventDataのみとしています。
Class ZAudit.Utils
{
/// 第1引数:出力ファイル名をフルパスで指定します。
/// 第2引数:ユーザ名を指定します。
ClassMethod OutputToFile(fname As %String, user As %String = "SuperUser")
{
set fo=##class(%Stream.FileCharacter).%New()
do fo.LinkToFile(fname)
//SQL実行用インスタンスを生成
set stmt=##class(%SQL.Statement).%New()
//定義されているストアドプロシージャはクラスクエリの形式でも利用できます。
//例ではクラスクエリを実行する方法を記載しています。
set status=stmt.%PrepareClassQuery("%SYS.Audit","ListByUser")
set rset=stmt.%Execute(,,,,,user) //第6引数に調査したいユーザ名を指定
#dim rset As %SQL.StatementResult
//TimeStamp と EventDataを出力します
do fo.WriteLine("TimeStamp,EventData")
while rset.%Next() {
do fo.Write(rset.%Get("TimeStamp")_",")
do fo.WriteLine(rset.%Get("EventData"))
}
set status=fo.%Save()
kill fo
}
}
実行例は以下の通りです。
%SYS>do ##class(ZAudit.Utils).OutputToFile("/usr/irissys/mgr/user/t2.csv","SuperUser")
注意:バージョン2022.1.3以前で実行する場合
EventDataプロパティが参照できないので以下コード例のように実行してください。
ClassMethod OutputToFile2(fname As %String, user As %String = "SuperUser")
{
set fo=##class(%Stream.FileCharacter).%New()
do fo.LinkToFile(fname)
//SQL実行用インスタンスを生成
set stmt=##class(%SQL.Statement).%New()
//定義されているストアドプロシージャはクラスクエリの形式でも利用できます。
//例ではクラスクエリを実行する方法を記載しています。
set status=stmt.%PrepareClassQuery("%SYS.Audit","ListByUser")
set rset=stmt.%Execute(,,,,,user) //第6引数に調査したいユーザ名を指定
#dim rset As %SQL.StatementResult
//TimeStamp と EventDataを出力します
do fo.WriteLine("TimeStamp,EventData")
while rset.%Next() {
set utc=rset.%Get("UTCTimeStamp")
set sid=rset.%Get("SystemID")
set aid=rset.%Get("AuditIndex")
set stauts=##class(%SYS.Audit).Get(utc,sid,aid,.data)
do fo.Write(rset.%Get("TimeStamp")_",")
do fo.WriteLine($get(data("EventData")))
kill data
}
set status=fo.%Save()
kill fo
}
記事
Toshihiko Minamoto · 2022年1月27日
はじめにバージョン2019.2より、InterSystems IRISは、高性能データアクセス手法としてPython用のネイティブAPIを提供してきました。 ネイティブAPIを使用すると、ネイティブのIRISデータ構造と直接対話することができます。グローバルInterSystems開発者であれば、おそらくすでにグローバルを理解していることでしょう。 ここでは、復習目的でその基本を確認しますが、次のセクションに進んでも構いません。InterSystems IRISはグローバルを使用してデータを格納しています。 グローバルは、値の有無に関係なくノードとサブノードで構成されるスパース配列です。 以下に、グローバルの概念的な例を示します。この例では、aはルートノードであり、グローバル名と呼ばれています。 各ノードには、グローバル名と1つまたは複数のサブスクリプト(サブノードの名前)で構成されるノードアドレスがあります。 aにはサブスクリプトbとcがあるため、それらのノードアドレスは、a->bおよびa->cとなります。ノードa->bとa->c->gには値(dとh)があり、ノードa->b->eとa->b->fには値がありません。 ノードa->bにはサブスクリプトeとfがあります。この構造の詳細な説明は、InterSystems dookbook『グローバルの使用法』に記載されています。グローバルの読み取りと書き込みネイティブのPython APIでは、IRISグローバルからデータを読み取りとそれへの書き込みを直接行えます。 irisnativeパッケージはGitHubで提供されています。または、InterSystems IRISがローカルマシンにインストールされている場合は、インストールディレクトリのdev/pythonサブディレクトリにあります。irisnative.createConnection関数は、IRISへの接続を作成し、irisnative.createIris関数は、この接続から、グローバルを操作するために使用するオブジェクトを取得します。 このオブジェクトには、グローバルの読み書きに使用するgetメソッドとsetメソッド、そしてノードとそのサブノードの削除に使用するkillメソッドがあります。 また、isDefinedメソッドもあり、このメソッドによって、リクエストされたノードが存在しない場合は「0」、
値があり子孫がない場合は「1」、値がなく子孫がある場合は「10」、値と子孫がある場合は「11」を返します。
import irisnative
conn = irisnative.createConnection("127.0.0.1", 51773, "USER", "", "")
iris = irisnative.createIris(conn)
iris.set("value", "root", "sub1", "sub2") # sets "value" to root->sub1->sub2
print(iris.get("root", "sub1", "sub2"))
print(iris.isDefined("root", "sub1"))
iris.kill("root")
conn.close()
また、特定のノードのサブノードをループするiteratorメソッドもあります。 (使用方法は次のセクションで説明します。)
各メソッドの詳細な説明については、APIドキュメントをご覧ください。
サンフランシスコのGTFSトランジットデータファイル
グローバルにデータを格納する
General Transit Feed Specification(GTFS)は、公共交通機関の時刻表と経路に関するフォーマットです。 IRISネイティブAPIを使用して、2019年6月10日のサンフランシスコのGTFSデータを処理する方法を見てみましょう。
まず、データファイルの情報をIRISグローバルに格納します。 (このデモでは、すべてのファイルと列を使用するわけではありません。) ファイルはCSV形式で、最初の行に列名、残りの行にデータが含まれます。 Pythonで、必要なインポートを開始し、IRISへの接続を確立します。
import csv
import irisnative
conn = irisnative.createConnection("127.0.0.1", 51773, "USER", "", "")
iris = irisnative.createIris(conn)
列名とデータに基づき、各ファイルの実用的なツリー構造を構築し、iris.setを使用してグローバルにデータを格納できます。
stops.txtファイルから始めましょう。このファイルにはサンフランシスコのすべての公共交通機関の停留所・停車駅が含まれます。 このファイルのstop_id列とstop_name列のみを使用します。 これらを、stop IDをサブスクリプト、stop nameをノードの値として使用し、1つのレイヤーのノードを持つツリー構造内のstopsというグローバルに格納します。 したがって、この構造は「stops → [stop_id]=[stop_name]」のようになります。 (この記事では、サブスクリプトがリテラルではなくデータファイルから読み取った値である場合に、角括弧を使用しています。)
with open("stops.txt", "r") as csvfile:
reader = csv.reader(csvfile)
next(reader) # Ignore column names
# stops -> [stop_id]=[stop_name]
for row in reader:
iris.set(row[6], "stops", row[4])
csv.readerは、カンマ区切りの値を保持するリストのイテレータを返します。 最初の行には列名が含まれているため、next(reader)を使ってその行をスキップします。 stop nameをstops -> [stop_id]の値として設定するために、 iris.setを使用します。
次はroutes.txtファイルです。このファイルのroute_type、route_id、route_short_name、およびroute_long_name列を使用します。 実用的なグローバル構造は、routes -> [route_type] -> [route_id] -> [route_short_name]=[route_long_name]です。 (route type(経路タイプ)は、路面電車の場合は「0」、バスの場合は「3」、ケーブルカーの場合は「5」です。) このCSVファイルからデータを読み取って、まったく同じようにグローバルに格納します。
with open("routes.txt", "r") as csvfile:
reader = csv.reader(csvfile)
next(reader) # Ignore column names
# routes -> [route_type] -> [route_id] -> [route_short_name]=[route_long_name]
for row in reader:
iris.set(row[0], "routes", row[1], row[5], row[8])
各経路には区間があります。これはtrips.txtファイルに格納されているもので、このファイルのroute_id、direction_id、trip_headsign、およびtrip_id列を使用します。 区間は、trip ID(後でstop timesファイルで確認します)で一意に識別されています。 ある経路の区間は、方向を基準とした2つのグループに分けられ、方向にはヘッドサインが関連付けられています。 これを踏まえると、ツリー構造はtrips -> [route_id] -> [direction_id]=[trip_headsign] -> [trip_id]となります。
ここでは2つのiris.set呼び出しが必要です。direction IDノードに値を設定する呼び出しと、trip IDの値のないノードを作成する呼び出しです。
with open("trips.txt", "r") as csvfile:
reader = csv.reader(csvfile)
next(reader) # Ignore column names
# trips -> [route_id] -> [direction_id]=[trip_headsign] ->[trip_id]
for row in reader:
iris.set(row[3], "trips", row[1], row[2])
iris.set(None, "trips", row[1], row[2], row[6])
最後に、stop times(停止時刻)を読み取って格納します。 これらは、stop_times.txtファイルに格納されており、このファイルのstop_id、trip_id、stop_sequence、departure_time列を使用します。 最初のオプションにはstoptimes -> [stop_id] -> [trip_id] -> [departure_time]を使用することができます。またはstop sequence(停止順)を維持する場合は、stoptimes -> [stop_id] -> [trip_id] -> [stop_sequence]=[departure_time]となります。
with open("stop_times.txt", "r") as csvfile:
reader = csv.reader(csvfile)
next(reader) # Ignore column names
# stoptimes -> [stop_id] -> [trip_id] -> [stop_sequence]=[departure_time]
for row in reader:
iris.set(row[2], "stoptimes", row[3], row[0], row[4])
ネイティブAPIを使用してデータをクエリする
次の目標は、特定の名前の停留所・停車駅のすべての出発時刻を見つけることです。
まず、特定のstop nameからstop IDを取得し、そのIDを使ってstop_timesから関連する時刻を見つけます。
iris.iterator("stops")呼び出しを使うと、stopsルートノードのサブノードを反復できます。 サブスクリプトと値のペアを反復したいため(指定された名前を持つ値を比較し、一致すればスフにサブスクリプトを知ることができるため)、イテレータで.items()を呼び出し、戻り値の型を (subscript, value) のタプルに設定します。 次に、これらすべてのタプルを反復して、正しいstopを見つけ出します。
stop_name = "Silver Ave & Holyoke St"
iter = iris.iterator("stops").items()
stop_id = None
for item in iter:
if item[1] == stop_name:
stop_id = item[0]
break
if stop_id is None:
print("Stop not found.")
import sys
sys.exit()
ノードが多数ある場合、反復によってキーの値でキーでルックアップするのはあまり効率的ではありません。 これを避けるには、サブスクリプトがstop nameで値がIDである別の配列を用意するとよいでしょう。 すると、value --> key ルックアップは、この新しい配列への1つのクエリで構成されます。
または、stop nameも一意であるため、stop IDの代わりに、コードのあらゆる箇所でstop nameを識別子として使用することもできます。
お分かりのとおり、stopsの数が膨大にある場合は、この検索に時間が掛かります。これは「フルスキャン」とも呼ばれています。 ただし、グローバルを利用して、値のIDを持つキーが名前となる逆配列を作成することができます。
iter = iris.iterator("stops").items()
stop_id = None
for item in iter:
iris.set(item[0], "stopnames", item[1])
インデックスが名前で値がIDのstopnamesグローバルがあることで、名前でstop_idを見つける上記のコードは、フルスキャン検索を行わずに実行する以下のコードに変更されます。
stop_name = "Silver Ave & Holyoke St"
stop_id=iris.get("stopnames", stop_name)
if stop_id is None:
print("Stop not found.")
import sys
sys.exit()
この時点で、stop times(停止時刻)を見つけることができます。 サブツリーstoptimes -> [stop_id]にはtrip IDサブノードがあり、このサブノードにはstop timesサブノードがあります。 trip IDではなく、stop timesのみに関心があるため、すべてのtrip IDを反復して、それぞれのすべてのstop timesを収集します。
all_stop_times = set()
trips = iris.iterator("stoptimes", stop_id).subscripts()
for trip in trips:
all_stop_times.update(iris.iterator("stoptimes", stop_id, trip).values())
ここでは、イテレータに.items()を使用していませんが、trip IDはサブスクリプトであるため.subscripts()と.values()を使用します。または、値とdeparture times(出発時刻)に関心がある場合には、下位レイヤー([stop_sequence]=[departure_time])を使用します。 .update呼び出しは、イテレータのすべての項目を既存のセットに追加します。 すると、セットにはすべての(一意の)stop timesが含まれます。
for stop_time in sorted(all_stop_times):
print(stop_time)
では、もう少し複雑にしてみましょう。 ある停車駅・停留所のすべての出発時刻を見つける代わりに、ある停車駅・停留所におけるroute IDが指定された特定の経路(両方向)のみの出発時刻を見つけることにします。 stop nameからstop IDを見つけ出すコードは、そのまま使用できます。 次に、特定の経路のすべてのtrip IDを取得します。 これらのIDは、departure timesを取得する際の追加の制限として使用されます。
trips -> [route_id]のサブセットは2つの方向に分割され、すべてのtrip IDがサブノードとなります。 前と同じようにdirectionsを反復し、すべてのdirectionsのサブノードをセットに追加します。
route = "14334"
selected_trips = set()
directions = iris.iterator("trips", route).subscripts()
for direction in directions:
selected_trips.update(iris.iterator("trips", route, direction).subscripts())
次のステップとして、取得されたstop IDを[stop_id]、選択されるtrip IDを[trip_id]とするstoptimes -> [stop_id] -> [trip_id]のすべてのサブノードの値を見つけ出します。 selected_tripsセットを反復して、すべての関連する値を見つけます。
all_stop_times = set()
for trip in selected_trips:
all_stop_times.update(iris.iterator("stoptimes", stop_id, trip).values())
for stop_time in sorted(all_stop_times):
print(stop_time)
最後の例では、isDefined関数の使用方法を示します。 以前に記述したコードを拡張し、route IDをハードコーディングする代わりに、経路の短縮名を指定すると、route IDはそれに基づいて取得されるようになります。 経路名のあるノードは、ツリーの最下位レイヤーにあります。 その上のレイヤーにはroute IDが含まれます。 すべての経路タイプを反復してからすべてroute IDを反復すると、ノードroutes -> [route_type] -> [route_id] -> [route_short_name]が存在して値がある(isDefinedが1を返す)場合は、探しているIDが[route_id]であることがわかります。
route_short_name = "44"
route = None
types = iris.iterator("routes").subscripts()
for type in types:
route_ids = iris.iterator("routes", type).subscripts()
for route_id in route_ids:
if iris.isDefined("routes", type, route_id, route_short_name) == 1:
route = route_id
if route is None:
print("No route found.")
import sys
sys.exit()
このコードは、ハードコーディングされたroute = "14334"の行の代わりになります
すべてのIRIS操作が完了したら、データベースへの接続を閉じることができます。
conn.close()
今後の内容
Python のネイティブAPIを使ってInterSystems IRIS のデータ構造にアクセスする方法を説明し、それをサンフランシスコの公共交通機関データに適用しました。 APIの詳細な説明については、ドキュメントをご覧ください。 ネイティブAPIは、Java、.NET、およびNode.jsで提供されています。
お知らせ
Mihoko Iijima · 2024年3月26日
開発者の皆さん、こんにちは。
(2024/5/30:6月の日時、ウェビナー内容を更新しました)
InterSystems IRIS、InterSystems IRIS for Healthの新バージョン2024.1がリリースされました。
様々な機能の追加や実験的機能としての追加が行われましたが、その中から以下3種類の内容についてウェビナーを開催します!📣
✅4月23日(火)13時半~14時:IRIS 2024.1の管理用Webサーバ(PWS)廃止に備えて
YouTube公開しました👉https://youtu.be/bVwWZt1oNws?list=PLzSN_5VbNaxCeC_ibw2l-xneMCwCVf-Or
✅5月30日(木)13時半~14時:ベクトル検索機能のご紹介
YouTube公開しました👉https://youtu.be/v0G7K2et_Yk?list=PLzSN_5VbNaxB39_H2QMMEG_EsNEFc0ASz
✅6月25日(火)13時半~14時:FHIR新機能のご紹介~2024.1~
オンデマンド配信はこちら👉https://event.on24.com/wcc/r/4597704/ADA161B6446E6BA01623C875CF596FD0(資料PDFもオンデマンド配信画面よりダウンロードいただけます)
ご参考:リリース案内記事
InterSystems IRIS Data Platform 2024.1 リリースのご案内
InterSystems IRIS for Health および HealthShare Health Connect 2024.1 リリースのご案内
ウェビナーでご案内する機能以外にも実験的機能も含め多くの機能が追加されていますので、以下簡単に概要をご紹介します。
現在日本語ドキュメントは鋭意翻訳中のため、仕上がるまでの間は英語ドキュメント(IRISリリースノート/IRIS for Healthリリースノート)をご参照ください。
管理系
✔ マルチボリュームデータベース: スケーラビリティとストレージ管理の強化
下図はデータベース新規作成の画面ですが、設定項目に [New Volume Threshold Size] の項目が追加されました。(ドキュメント:Configuring a Multivolume Database)
この値を 0 より大きい値に設定した場合、DATが指定サイズを超えると指定フォルダ内に IRIS-000x.VOL というデータベースを作ります。(拡張ファイルとして指定サイズで区切ったデータベースファイルが作成できるようになりました)
✔ ファスト・オンライン・バックアップ(実験的機能): バックアッププロセスの合理化
以前より、外部バックアップ(Backup.GeneralクラスのExternalFreeze()/ExternalThaw()を利用する方法)と、オンラインバックアップを提供していますが、このリリースの実験的機能追加は「オンラインバックアップ」に対しての高速化とクラスAPIの用意です。(Bakcup.Onlineクラスが追加されました)
現段階では、Backup.Onlineクラスを利用したバックアップに対しての高速化が行われています。管理ポータルメニューからの実行やDBACKルーチンを利用した実行には影響がありません。お試しいただく場合は、Early Access Program(EAP)へのお申込みをどうそよろしくお願いします。
✔ 複数のスーパーサーバポート: ネットワーク構成の柔軟性を提供
お馴染みの1972番以外のポート番号をスーパーサーバポートとして追加できるようになりました。(JDBC/ODBC経由のアクセスがある時は別ポートでアクセス、など柔軟に対応できるようになりました)
設定は、管理ポータル > [システム管理] > [セキュリティ] > [Superservers] から行えます。(ドキュメント:Managing SuperServers)
52774のポートを追加した例:
JDBCでの接続の例
import java.sql.*;
import java.util.Scanner;
import com.intersystems.jdbc.*;
public class JDBCTest {
public static void main(String[] args) throws Exception {
//接続文字列
String url = "jdbc:IRIS://localhost:52774/USER";
Class.forName("com.intersystems.jdbc.IRISDriver").newInstance();
//com.intersystems.jdbc.IRISDataSource を使用し、java.sql.Connectionオブジェクトを作成
IRISDataSource ds = new IRISDataSource();
ds.setURL(url);
ds.setUser("SUPERUSER");
ds.setPassword("SYS");
Connection connection = ds.getConnection();
//SELECT実行
String query = "SELECT ID,Name,Email FROM Test.Person";
PreparedStatement statement = connection.prepareStatement(query);
ResultSet resultSet = statement.executeQuery();
System.out.println("\n*** SELECTの結果 ****");
while (resultSet.next()) {
System.out.println(resultSet.getString(1) + " - " + resultSet.getString(2)+ " - " + resultSet.getString(3));
}
resultSet.close();
statement.close();
connection.close();
}
}
SQL
✔ JSON_TABLE関数、With句のサポート追加
(ドキュメント:JSON_TABLE (SQL)/WITH (SQL))
JSON_TABLE()関数では、%Net.GetJson()を利用して外部サイトからの結果をそのまま使用することもできます。
例)zipcloudのAPIを使用した例です。
〒0790177で取得できる結果のJSONを使用しています(https://zipcloud.ibsnet.co.jp/api/search?zipcode=0790177)
メモ:httpsを使用するため、%Net.GetJson()の第2パラメータに予め管理ポータルで設定したSSL/TLS構成名を指定しています。
設定は、 [システム管理] > [セキュリティ] > [SSL/TLS構成] メニューを開き、「構成名」に任意名を設定し、「保存」ボタンをクリックします(そのほかの構成パラメータは、デフォルト値で作成します)。
例では、”test” の名称で作成した構成名を指定しています。({"SSLConfigration":"test"})
SELECT address1,address2,address3,kana1,kana2,kana3,zipcode
FROM JSON_TABLE(%Net.GetJson('https://zipcloud.ibsnet.co.jp/api/search?zipcode=0790177','{"SSLConfiguration":"test"}')
,
'$.content.results'
COLUMNS ( address1 VARCHAR(100) PATH '$.address1',
address2 VARCHAR(100) PATH '$.address2',
address3 VARCHAR(100) PATH '$.address3',
kana1 VARCHAR(100) PATH '$.kana1',
kana2 VARCHAR(100) PATH '$.kana2',
kana3 VARCHAR(100) PATH '$.kana3',
zipcode VARCHAR(10) PATH '$.zipcode')
) as jt
ORDER BY address3
《結果》
✔ 安全なクエリ中止(CANCEL QUERY)
このリリースでInterSystems SQL に実行中のステートメントを中止し、実行により使用されていたメモリや一時領域などを安全に開放する新しいコマンド CANCEL QUERY が追加されました。
✔ クエリパフォーマンスを向上させる機能強化
グローバルイテレータでは、ObjectScriptを使用せずに、インデックスおよびデータマップを参照する処理の多くをカーネル内部モジュールで実行します。
Adaptive Parallel Execution (APE; アダプティブ並列実行) フレームワークでカラムナーストレージを含むクエリに初めて対応しました。APEでは個別の並列サブクエリをプリペアして実行するのではなく、メインクエリとして同じクエリキャッシュクラスを並列ワーカーコードとして生成します。
Embedded Python
✔ Pythonランタイムが選択可能に(Windowsを除く)
Linuxベースの環境限定となりますが、管理ポータルでPythonランタイムを指定できるようになりました。(ドキュメント:Flexible Python Runtime Feature)
管理ポータル > [システム管理] > [構成] > [追加の設定] > [メモリ詳細] > [PythonRuntimeLibrary]
PythonRuntimeLibrary構成設定詳細(英語)
✔ BPLエディタ内でPythonの記述が可能に
Interoprabilityで使用するビジネス・プロセスのエディタの1つであるBPLエディタ内のCodeアクティビティにEmbedded Pythonが記述できるようになりました。
✔ Python WSGI標準準拠のWebアプリが作成可能に(実験的機能)
IRISのインスタンス内部でEmbedded Pythonを使用して flask や Django などの WSGI 準拠フレームワークを実行することができるようになりました。
(ドキュメント:Creating WSGI Applications)
WSGIのWebアプリの実行を指定するために、管理ポータルの以下メニューや用意されました。
管理ポータル > [システム管理] > [セキュリティ] > [アプリケーション] > [ウェブ・アプリケーション]
図の設定では、http://Webサーバ/flaskapp が指定されるとFlaskで記述している flasktest アプリケーションが呼び出されます。
メモ:例では、パスを通過した後に付与されるアプリケーション・ロールを指定しています。本来であれば適切なロールを用意し付与しますが簡易的に試すためフルアクセスできる%Allを付与しています)
この例のWebサーバ(localhost:8080)に対してパスを指定すると以下の画面が表示されます。画面でID番号を入力すると、指定IDを条件にIRISにあるテーブルに対してSELECT文が実行されレコードの中身が表示されます。
以下ご参考(コード例):
Pythonのコード
from flask import Flask, render_template, request
## Embedded Python ここから ##
import sys
sys.path+=['/usr/irissys/mgr/python','/usr/irissys/lib/python']
def getOnePerson(id):
import iris
sql="select ID,Name,Email,TOCHAR(DOB,'YYYY-MM-DD') from Test.Person WHERE ID=?"
stmt=iris.sql.prepare(sql)
rset=stmt.execute(id)
reco=rset.__next__()
return reco
### Embedded Python ここまで ###
## Flask ##
app = Flask(__name__)
@app.route('/',methods=['GET'])
def person() -> str:
return render_template("start.html",post="")
@app.route('/', methods=['POST'])
def personsearch():
pid=request.form['pid']
post=getOnePerson(pid)
#print(post)
return render_template("start.html",post=post)
if __name__ == '__main__':
app.run(debug=True,host="0.0.0.0",port=8090)
使用しているHTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
<title>IRISのデータ参照する</title>
</head>
<body>
<nav class="navbar navbar-light" style="background-color: #e3f2fd;"">
<a class="navbar-brand pl-3" href="/flasktest/" style="font-size: 2rem;">Person検索!</a>
</nav>
<h2>情報入力</h2>
<div class="form">
<form action="/flasktest/" method='POST'>
<label for="title">PersonのIDを入力してください:
</label>
<input type="text" name="pid" value={{ post[0] }}>
<input type="submit" value="Person検索">
</form>
{% if post != "" %}
<div>
<table class="table table-light table-striped">
<tr><th>名前</th><td>{{post[1]}}</td></tr>
<tr><th>Email</th><td>{{post[2]}}</td></tr>
<tr><th>誕生日</th><td>{{post[3]}}</td></tr>
</table>
</div>
{% endif %}
</div>
</body>
</html>
新機能紹介ウェビナー第2段、5月開催詳細が決定しました!
✅5月30日(木)13時半~14時:ベクトル検索機能のご紹介
お申し込みは👉https://event.on24.com/wcc/r/4571564/A10293B27D767898A19C5B73188BF7DE
4月開催分のオンデマンド視聴開始しました。ぜひご覧ください。
✅4月ウェビナー:IRIS 2024.1の管理用Webサーバ(PWS)廃止に備えて
オンデマンド視聴できます👉https://event.on24.com/wcc/r/4515226/1323ED7EECDC5A18B293BC2BCFDD3A9C 新機能紹介ウェビナー第3弾、6月開催詳細が決定しました!
✅6月25日(火)13時半~14時:FHIR新機能のご紹介~2024.1~
お申し込みは👉https://event.on24.com/wcc/r/4597704/ADA161B6446E6BA01623C875CF596FD0
5月開催分のオンデマンド視聴開始しました。ぜひご覧ください。
✅5月30日(木)13時半~14時:ベクトル検索機能のご紹介
https://event.on24.com/wcc/r/4571564/A10293B27D767898A19C5B73188BF7DE
記事
Toshihiko Minamoto · 2022年10月19日
しばらく前、IRIS 用 Django の新しいドライバーを導入しました。 そこで実際に、IRIS で Django を使用する方法を見てみましょう。

_重要な注意事項: IRIS Community Edition で Django を使用してもほぼまったく動作しません。Community Edition には利用できる接続が 5 つしかなく、Django がすぐに使い果たしてしまうためです。 残念ながらこの理由により、ライセンスの使用状況を予測するのが難しいため、新しいアプリケーションの開発にはこの方法をお勧めできません。_
## Django プロジェクトを開始する
新しい Django プロジェクトを開始しましょう。そのためにはまず、Django そのものをインストールする必要があります。
pip install django
次に、demo という名前のプロジェクトを作成します。プロジェクトフォルダが同じ名前で作成されます。
django-admin startproject demo
cd demo
または、既存のフォルダを使用することもできます。
django-admin startproject main .
このコマンドにより、いくつかの Python ファイルが作られます。
.png)
ファイルの説明:
* **manage.py:** この Django プロジェクトを様々な方法で操作するためのコマンドラインユーティリティ
* **main** ディレクトリ: プロジェクトの実際の Python パッケージ
* **main/\_\_init\_\_.py:** このディレクトリを Python パッケージと見なすように Python に伝達する空のファイル
* **main/settings.py**: この Django プロジェクトの設定/構成
* **main/urls.py**: この Django プロジェクトの URL 宣言。Django で作られたサイトの「目次」。
* **main/asci.py**: プロジェクトにサービスを提供するための ASGI 対応ウェブサーバーのエントリポイント。
* **main/wsci.py**: プロジェクトにサービスを提供するための WSGI 対応ウェブサーバーのエントリポイント。
このポイントからでもプロジェクトを開始することが可能で、何とか機能します。
$ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced). You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
July 22, 2022 - 15:24:12
Django version 4.0.6, using settings 'main.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
ブラウザに移動して、URL http://127.0.0.1:8000 を開きます。
.png)
## IRIS を追加する
IRIS へのアクセスを追加しましょう。それには、プロジェクトに依存関係をいくつかインストールする必要があります. 正しい方法は、_以下の内容で、django を依存関係として追加する requirements.txt_ というファイルに定義することです。
# Django itself
django>=4.0.0
次は、公開されている Django の IRIS 用ドライバーです。 _残念ながら、InterSystems には独自のドライバーを PyPI に公開する意向がないため、以下の方法でそれを定義しなければなりません。 これがいつ削除されるかわからないため、将来的には動作しない可能性もあるので注意してください。 (pypi にあるのであれば、django-iris の依存関係としてインストールされ、明示的に定義される必要がないかもしれません)_
# InterSystems IRIS driver for Django, and DB-API driver from InterSystems
django-iris==0.1.13
https://raw.githubusercontent.com/intersystems-community/iris-driver-distribution/main/DB-API/intersystems_irispython-3.2.0-py3-none-any.whl
このファイルに定義されている依存関係を次のコマンドでインストールします。
pip install -r requirements.txt
次に、プロジェクトが IRIS を使用するように構成できます。それには、_settings.py_ ファイルの **DATABASES** パラメーターを以下のような行で更新する必要があります。NAME は IRIS のネームスペース、PORT は IRIS を利用できる SuperPort を指します。
DATABASES = {
'default': {
'ENGINE': 'django_iris',
'NAME': 'USER',
'USER': '_SYSTEM',
'PASSWORD': 'SYS',
'HOST': 'localhost',
'PORT': 1982,
}
}
Django には ORM と、プロジェクトに格納されたモデルがあり、Django モデルと Database をテーブルとして同期する必要があります。 デフォルトでは、auth に関連するモデルがいくつかあります。 ここで、migrate を実行できます。
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OK
IRIS に移動すると、追加のテーブルがあります。
.png)
## さらにモデルを定義する
では、モデルを追加しましょう。 それには、次のような内容で _models.py,_ という新しいファイルを追加します。
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
dob = models.DateField()
sex = models.BooleanField()
見てのとおり、様々な型のフィールがあります。 次に、このモデルを Database 用に準備する必要がありますが、 その前に、**main** プロジェクトを _settings.py_ の **INSTALLED_APPS** に追加します。
INSTALLED_APPS = [
....
'main',
]
次に、makemigrations を行います。 このコマンドは、モデルに変更があった後に呼び出される必要があります。モデルの過去の変更に対応し、インストールされているアプリケーションのバージョンに関係なく、migration はデータベースのスキーマをどのように更新すべきかを認識しています。
$ python manage.py makemigrations main
Migrations for 'main':
main/migrations/0001_initial.py
- Create model Person
もう一度 migrate を実行しますが、以前の migrations がすでに実行されたことをわかっているため、新しいものだけが実行されます。
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, main, sessions
Running migrations:
Applying main.0001_initial... OK
そして実際に、SQL ビューから migration がどのように見えるかを確認できます。
$ python manage.py sqlmigrate main 0001
--
-- Create model Person
--
CREATE TABLE "main_person" ("id" BIGINT AUTO_INCREMENT NOT NULL PRIMARY KEY, "first_name" VARCHAR(30) NULL, "last_name" VARCHAR(30) NULL, "dob" DATE NOT NULL, "sex" BIT NOT NULL);
ただし、作業アプリケーションがすでに存在する場合などには、データベースにすでに存在するテーブルにアクセスすることが可能です。 zpm package posts-and-tags がインストールされているので、community.posts テーブルのモデルを作成しましょう。
$ python manage.py inspectdb community.post
# This is an auto-generated Django model module.
# You'll have to do the following manually to clean this up:
# * Rearrange models' order
# * Make sure each model has one field with primary_key=True
# * Make sure each ForeignKey and OneToOneField has `on_delete` set to the desired behavior
# * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
# Feel free to rename the models, but don't rename db_table values or field names.
from django.db import models
class CommunityPost(models.Model):
id = models.AutoField(db_column='ID') # Field name made lowercase.
acceptedanswerts = models.DateTimeField(db_column='AcceptedAnswerTS', blank=True, null=True) # Field name made lowercase.
author = models.CharField(db_column='Author', max_length=50, blank=True, null=True) # Field name made lowercase.
avgvote = models.IntegerField(db_column='AvgVote', blank=True, null=True) # Field name made lowercase.
commentsamount = models.IntegerField(db_column='CommentsAmount', blank=True, null=True) # Field name made lowercase.
created = models.DateTimeField(db_column='Created', blank=True, null=True) # Field name made lowercase.
deleted = models.BooleanField(db_column='Deleted', blank=True, null=True) # Field name made lowercase.
favscount = models.IntegerField(db_column='FavsCount', blank=True, null=True) # Field name made lowercase.
hascorrectanswer = models.BooleanField(db_column='HasCorrectAnswer', blank=True, null=True) # Field name made lowercase.
hash = models.CharField(db_column='Hash', max_length=50, blank=True, null=True) # Field name made lowercase.
lang = models.CharField(db_column='Lang', max_length=50, blank=True, null=True) # Field name made lowercase.
name = models.CharField(db_column='Name', max_length=250, blank=True, null=True) # Field name made lowercase.
nid = models.IntegerField(db_column='Nid', primary_key=True) # Field name made lowercase.
posttype = models.CharField(db_column='PostType', max_length=50, blank=True, null=True) # Field name made lowercase.
published = models.BooleanField(db_column='Published', blank=True, null=True) # Field name made lowercase.
publisheddate = models.DateTimeField(db_column='PublishedDate', blank=True, null=True) # Field name made lowercase.
subscount = models.IntegerField(db_column='SubsCount', blank=True, null=True) # Field name made lowercase.
tags = models.CharField(db_column='Tags', max_length=350, blank=True, null=True) # Field name made lowercase.
text = models.CharField(db_column='Text', max_length=-1, blank=True, null=True) # Field name made lowercase.
translated = models.BooleanField(db_column='Translated', blank=True, null=True) # Field name made lowercase.
type = models.CharField(db_column='Type', max_length=50, blank=True, null=True) # Field name made lowercase.
views = models.IntegerField(db_column='Views', blank=True, null=True) # Field name made lowercase.
votesamount = models.IntegerField(db_column='VotesAmount', blank=True, null=True) # Field name made lowercase.
class Meta:
managed = False
db_table = 'community.post'
**managed = False** にマークされているため、makemigrations と migrate はこのテーブルで動作しません。 テーブル名を省略すると、Django が以前に作成したテーブルも含む、大規模なモジュールのリストが生成されます。
記事
Toshihiko Minamoto · 2021年8月24日
ソリューションを Amazon Web Services エコシステム、サーバーレスアプリケーション、または `boto3` を使用した Python スクリプトにスムーズに統合する方法を探している場合は、[IRIS Python Native API](https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=AFL_PYNATIVE) を使用するのが最適です。 IRIS で何かを取得したり設定したりしてアプリケーションに素晴らしい機能を備える必要があるまで、本番の実装を大々的に構築する必要はありません。したがって、誰かにとって重要なものまたはあなた以外にはまったく重要でないもの(これも同じくらい重要なことです)を構築できるようにこの記事が役に立てればと思います。

これを実装する口実が必要であれば
* OAUTH2 ワークフローを実装する FHIR(R) ベースソリューションで Patient ID コンテキストを調べ、SHMAHT のトークンに挿入するために Pre Token Generation Trigger を使用する必要がある。
* インスタンスタイプ、ノードグループ、Toaster、または ECS クラスタに応じてプロビジョニング後の IRIS チューニング設定を行い、リングゼロで IRIS を実行したい。
* AWS CLI でシェルを終了することなく IRIS を管理できるスキルを Zoom で家族や友人に披露したい。
## ポイント
ここでは、IRIS と対話できる AWS lambda 関数を示し、それをプロビジョニングする方法とさまざまなキャパシティで操作する方法についての例をいくつか説明します。これに関する対話を持つことで、**物事をより簡単に実現できる pip を公開**できるようになることを願っています。
## お急ぎですか????

Stream をご覧ください。
## そうでない方は…
このお楽しみに参加するには、現在のフライトプランから項目をいくつか削除する必要があります。
### ネットワークの構築
IRIS の実行 OS は問いませんが、きっかり 2 つのサブネットを使用する AWS VPC で実行しており、IRIS を実行しているスーパーサーバーへのアクセスを許可するセキュリティグループが必要です。懐かしさと InterSystems が時間を掛けて [IANA](https://tools.ietf.org/html/rfc6335) に登録したという単なる事実からポート 1972 を使用していますが、時間を掛けずに新しいポートを `/etc/services` に追加する場合は、新しいマットレスのタグを引きちぎるのと同じくらいに大変な思いをすることでしょう。 私たちの場合、AWS v2 ネットワークロードバランサーに適切なヘルスチェックを備えた ec2 インスタンスのミラーセットです。

### インポートしたサンプルのクラス
どうにかして、このリポジトリのルートにクラスを作成して IRIS インスタンスの `%SYS` ネームスペースにインポートすることができました。 以下は、上記の出力を駆動するクラスの例です。 ここでクラスをインポートする必要がある理由に疑問を持っている場合は、以下の注意事項をご覧ください。Python で使用するラッパークラスをプロビジョニングすることがアプローチとして推奨されています。
> ドキュメントから抜粋した注意事項: これらのメソッドはクラスライブラリに定義されている InterSystems クラスと使用することもできますが、メソッドをユーザー定義クラスまたはルーチン内から間接的に呼び出す方法をベストプラクティスとしています。 多くのクラスメソッドはステータスコードのみを返し、実際の結果は引数に返されます(Native API はアクセスできません)。 システム定義関数(ObjectScript リファレンスの ObjectScript 関数に記載された関数)を直接呼び出すことはできません。
サンプルのクラス:
```
Class ZDEMO.IRIS.Lambda.Operations Extends %Persistent
{
ClassMethod Version() As %String
{
Set tSC = 0
Set tVersion = $ZV
if ( tVersion '="" ) { set tSC = $$$OK }
Set jsonret = {}
Set jsonret.status = tSC
Set jsonret.payload = tVersion
Quit jsonret.%ToJSON()
}
}
```
ここでは慣習に基づいて作業し、常に JSON オブジェクトをレスポンスとして返すことにしました。こうすればステータスを返すことも可能で、参照によって何かを返せばギャップを埋められるかもしれません。
### AWS アクセス
世界を変えようとしている Lambda 関数をプロビジョニングして呼び出せるように、IAM アクセスキーを取得してください。
飛行前チェック:
```
IRIS [ $$$OK ]
VPC [ $$$OK ]
Subnets [ $$$OK ]
Security Group [ $$$OK ]
IAM Access [ $$$OK ]
Imported Class [ $$$OK ]
```
$$$OK, **レスゴー**。
## Lambda 関数で使用する IRIS Native Python API をパッキング
AWS Lambda 関数は Linux の Boxen 上で実行するため、これは、特に Linux のみの場合に pip パッケージであれば素晴らしい部分です。 このコミットの時点では、API は pip 経由で使用できませんが、リソースは豊富に備えているため、独自のものを用意することができます。
```
mkdir iris_native_lambda
cd iris_native_lambda
wget https://github.com/intersystems/quickstarts-python/raw/master/Solutions/nativeAPI_wheel/irisnative-1.0.0-cp34-abi3-linux_x86_64.whl
unzip nativeAPI_wheel/irisnative-1.0.0-cp34-abi3-linux_x86_64.whl
```
`connection.config` を作成します。
例: [connection.config](https://raw.githubusercontent.com/basenube/iris_native_lambda/main/examples/connection.config)
ハンドラー `index.py` を作成するか、[demo github リポジトリ](https://github.com/basenube/iris_native_lambda)の examples フォルダにあるものを使用します。 デモバージョンでは、IRIS 接続情報に環境変数と外部ファイルの両方が使用されていることに注意してください。
例:
[index.py](https://raw.githubusercontent.com/basenube/iris_native_lambda/main/examples/index.py)
使用できるようどのように zip 圧縮するか。
```
zip -r9 ../iris_native_lambda.zip *
```
S3 バケットを作成し、関数の zip をそれにアップロードします。
```
cd ..
aws s3 mb s3://iris-native-bucket
s3 sync iris_native_lambda.zip s3://iris-native-bucket
```
> これで、AWS Lambda 関数として使用する API とハンドラーのパッケージ化は完了です。
では、コンソールをクリックして関数を作成するか、Cloudformation などを使用して作成します。
```
IRISAPIFunction:
Type: "AWS::Lambda::Function"
DependsOn:
- IRISSG
- VPC
Properties:
Environment:
Variables:
IRISHOST: "172.31.0.10"
IRISPORT: "1972"
NAMESPACE: "%SYS"
USERNAME: "intersystems"
PASSWORD: "lovetheyneighbor"
Code:
S3Bucket: iris-native-bucket
S3Key: iris_native_lambda.zip
Description: "IRIS Native Python API Function"
FunctionName: iris-native-lambda
Handler: "index.lambda_handler"
MemorySize: 128
Role: "arn:aws:iam::8675309:role/BeKindtoOneAnother"
Runtime: "python3.7"
Timeout: 30
VpcConfig:
SubnetIds:
- !GetAtt
- SubnetPrivate1
- Outputs.SubnetId
- !GetAtt
- SubnetPrivate2
- Outputs.SubnetId
SecurityGroupIds:
- !Ref IRISSG
```
大変な作業でしたが、これで Python でラムダ関数を使って IRI を呼び出せるようになりました。世界が大きく変わります。
## 実行!
上記の実装方法では、関数は、再利用できるように構造化されたイベントオブジェクトに渡すことが期待されています。この考え方は以下のイベントオブジェクトの例で確認できます。
```
{
"method": "Version",
# important, if method requires no args, enforce "none"
"args": "none"
# example method with args, comma seperated
# "args": "thing1, thing2"
}
```
コマンドラインの例に我慢できるのであれば、AWS CLI を使用して実行を確認できます。
```
(base) sween @ basenube-pop-os ~/Desktop/BASENUBE
└─ $ ▶ aws lambda invoke --function-name iris-native-lambda --payload '{"method":"Version","args":"none"}' --invocation-type RequestResponse --cli-binary-format raw-in-base64-out --region us-east-2 --profile default /dev/stdout
{{\"status\":1,\"payload\":\"IRIS for UNIX (Red Hat Enterprise Linux for x86-64) 2020.2 (Build 210U) Thu Jun 4 2020 15:48:46 EDT\"}"
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
```
さらに踏み込めば、AWS CLI はエイリアスをサポートしているため、エイリアスを作成して AMS コマンドに完全に統合してみることができます。 以下に CLI エイリアスの例を示します。
```
└─ $ ▶ cat ~/.aws/cli/alias
[toplevel]
whoami = sts get-caller-identity
iris =
!f() {
aws lambda invoke \
--function-name iris-native-lambda \
--payload \
"{\"method\":\""${1}"\",\"args\":\"none\"}" \
--invocation-type RequestResponse \
--log-type None \
--cli-binary-format raw-in-base64-out \
gar.json > /dev/null
cat gar.json
echo
echo
}; f
```
ぜひお試しあれ!

それではお元気で!技術的な議論をお待ちしてます!
記事
Megumi Kakechi · 2021年3月10日
これは InterSystems FAQ サイトの記事です。
REST アプリケーションはステートレスであることが想定されています。
しかし、複数の REST 呼び出し間でデータを保持したい場合などの理由で、Webセッションを使用したい場合は、UseSession パラメータを使用することができます。
以下のように、Web アプリケーションのディスパッチクラスとして定義された %CSP.REST のサブクラスでUseSession パラメータを指定することで、CSPと同じようにWebセッションを使用することが可能となります。
Class REST.MyServices Extends %CSP.REST
{
Parameter UseSession As Integer = 1;
詳細は以下のドキュメントをご覧ください。
REST での Web セッションの使用
以下は、UseSession パラメータを使用した簡単なサンプルになります。最初に、2つのクラスを作成してください。
* REST.SessionTest.cls
Class REST.SessionTest Extends %CSP.REST
{
Parameter UseSession As Integer = 1;
XData UrlMap
{
<Routes>
<Route Url="/test/" Method="GET" Call="test"/>
</Routes>
}
ClassMethod test() As %Status
{
write "{""SessionId"":"""_%session.SessionId_"""}"
quit $$$OK
}
}
* REST.test.cls
Class REST.test Extends %CSP.Page
{
ClassMethod OnPage() As %Status
{
&html<
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<script type="text/javascript" src="http://code.jquery.com/jquery-2.2.4.js"></script>
<script type="text/javascript">
function go() {
$.ajax({
type:'GET',
dataType:'json',
url:'/csp/user/rest/test/',
success:function(data) {
ans = '';
for(var i in data) {
ans = ans + '\n' + JSON.stringify(data[i]);
}
alert(ans);
}
});
return;
}
</script>
</head>
<body>
<form name="xxx" method="post" action="">
<input type="button" name="test" onclick="go();" value="push" /></p>
</form>
Session ID: #(%session.SessionId)#<br>
</body>
</html>
サンプルの使用方法は以下になります。
1. 上記2つのクラスをUSERネームスペースに作成し、コンパイルする
2. ウェブアプリケーション /csp/user/rest を作成、 ディスパッチクラスに REST.SessionTest を設定、 セッションCookieパスを /csp/user に変更して保存
3. ブラウザで /csp/user/REST.test.cls を開いて、push ボタンを押す
記事
Toshihiko Minamoto · 2020年9月9日
最近の大規模なベンチマーク活動で、アプリケーションのスケーリングに悪影響を与える過度の %sys CPU 時間が観察されました。
**問題**
TZ 環境変数が設定されていないため、 _localtime()_ システムコールに多くの時間が費やされていることがわかりました。 観察結果を確認するための単純なテストルーチンが作成されましたが、TZ が設定されている場合と TZ が未設定の場合とでは経過時間と必要な CPUリソースが驚くほど違っていました。 TZ が設定されていない場合、_localtime()_ から /etc/local_time への _stat()_ システムコールの継承使用は非常に負荷が高いことがわかりました。
**推奨事項**
InterSystems は、x86 または Linux on Power のいずれの Linux インストール環境でも、TZ 環境変数を適切に設定して最適なパフォーマンスを確保することを強く推奨しています。 詳細については、「man tzset」を参照してください。
現在の Caché 2016.1のフィールドテストでは日付および時刻関連の関数に関する最適化が行われており、初期テストでは大幅に改善していることがわかっています。 以下は、TZ が設定されていない場合に PowerPC上のLinuxで新しい内部関数の呼び出しをテストした結果の出力例です。
Caché 2016.1 FT 未満:
real 0m22.60s
user 0m1.64s
sys 0m20.89s
Caché 2016.1 FT の場合:
real 0m0.40s
user 0m0.37s
sys 0m0.00s
皆さんが TZ 環境変数に関してアプリケーションで経験したことや、TZ 環境変数の設定有無による Caché 2016.1 のフィールドテストへの影響についてコメントを投稿してください。
記事
Megumi Kakechi · 2023年3月8日
これは InterSystems FAQ サイトの記事です。
^%GCMP ユーティリティにて2つのグローバルの内容を比較することができます。
例としてUSERとSAMPLESネームスペースにある、^testと^testを比較する場合は以下のようになります。※以下の例では、2つのネームスペースに全く同じグローバルを700個作り、その中の一つの中身を変えて検出対象としています。
USER>kill ^test // USERネームスペースに、比較元のグローバル作成(削除したあとに作成)
USER>for i=1:1:100 { for j=1:1:7 { set ^test(i,j)="テスト"_i } }
USER>zn "samples" // SAMPLESネームスペースに、比較先のグローバル作成(削除したあとに作成)
SAMPLES>kill ^test
SAMPLES>for i=1:1:100 { for j=1:1:7 { set ^test(i,j)="テスト"_i } }
SAMPLES>set ^test(50,5,1)=1 // SAMPLESネームスペースに作成したグローバルの一つを変更
SAMPLES>do ^%GCMP
Compare global ^test // 比較したいグローバル
on directory set: (this system) // Enter
in namespace: SAMPLES => // Enter(このネームスペースで良ければ)
with global ^test=> // 比較相手のグローバル
on directory set: (this system) // Enter
in namespace: SAMPLES => USER // 比較相手のネームスペース
Output differences on
Device: // 結果出力先、ターミナルで見る場合は <Enter> 押下
// ※ログファイル名をフルパスで書けば、そちらに出力される
Right margin: 80 =>
Compare global ^test in SAMPLES
with global ^test in USER
^test(50,5,1) exists in ^|"SAMPLES"|test but not in ^|"USER"|test // 相違のあるグローバルを検出
Time=.001822
SAMPLES>
同一インスタンス内ではなく、異なるサーバのインスタンス間での比較を行いたい場合は、^DATACHECKユーティリティを使用します。^DATACHECKユーティリティの使用方法については、以下の関連記事をご覧ください。
【関連】2つのデータベースにある複数のグローバルやルーチンを比較する方法
記事
Mihoko Iijima · 2020年10月25日
これはInterSystems FAQ サイトの記事です。
%Net.HttpRequest クラスの SSLConfiguration プロパティに SSL/TLS 構成の「クライアント」構成名が指定されているかご確認ください。
%Net.HttpRequest クラスを使用して、https の url にアクセスするためには、以下のドキュメントに記載されている SSL/TLS 構成 の「クライアント」構成を作成して指定した名前を SSLConfiguration プロパティに指定する必要があります。
SSL/TLS構成のクライアント構成方法
管理ポータルの [システム管理] > [セキュリティ] > [SSL/TLS構成] メニューを開き、「構成名」に任意名を設定し、「保存」ボタンをクリックします(そのほかの構成パラメータは、デフォルト値で作成します)。
実行例は以下の通りです(https://www3.nhk.or.jp/news/ にアクセスしています)。
set httprequest=##class(%Net.HttpRequest).%New()set httprequest.Https=1set httprequest.Server="www.nhk.or.jp"set httprequest.SSLConfiguration="test1" //設定したSSL/TSL構成名を指定set st=httprequest.Get("/news/")write $ZCVT(httprequest.HttpResponse.Data.Read(1000),"I","UTF8") // 取得できたレスポンスの一部を表示<!DOCTYPE HTML><!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7 eq-ie6"> <![endif]--><!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8 eq-ie7"> <![endif]--><!--[if IE 8]> <html class="no-js lt-ie9 eq-ie8"> <![endif]--><!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]--><head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# website: http://ogp.me/ns/website#"><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta http-equiv="X-UA-Compatible" content="requiresActiveX=true" />
<title>NHKニュースサイト 日本全国・世界の速報、最新情報|NHK NEWS WEB</title><meta name="robots" content="noodp,noarchive"><meta name="keywords" content="NHK,ニュース,NHK NEWS WEB" /><meta name="description" content="NHKのニュースサイト「NHK NEWS WEB」。国内外の取材網を生かし、さまざまな分野のニュース をいち早く、正確にお伝えします。ニュース
記事
Hiroshi Sato · 2021年9月9日
これは InterSystems FAQ サイトの記事です。
2025.1以降CORS関連の設定方法は大きく変わっています。
詳細は、以下の記事を参照してください。
jQueryを使用してIRISからJSONデータを取得する方法
%CSP.REST クラスを継承する REST 用ディスパッチクラスで REST を実装している場合は、クロスドメイン制約回避用に用意されたパラメータ HandleCorsRequest を利用します。
設定方法は以下の通りです。
REST 用ディスパッチクラスをスタジオで修正する場合は、[クラス] > [リファクタ] > [オーバーライド] を開き、[パラメータ]タブを選択 > [HandleCorsRequest] を選択後OKボタンを押下します。
以下の定義が追加されるので、1を設定します。
Parameter HandleCorsRequest=1;
REST ディスパッチクラスを Atelier で修正する場合は、オーバーライドメニューの用意がないため、パラメータの定義を追加するか、%CSP.REST クラスを開き、HandleCorsRequest の定義をコピーし修正します。
パラメータ:HandleCorsRequest 他に、REST 用ディスパッチクラスに用意する URL マップ(URL に対応するメソッドのマップ定義)の Route 要素毎に Cors 属性を true に設定する方法でも回避できます。メモ:Cors 属性はデフォルトでは false が設定されています。
XData UrlMap{<Routes><Route Url="/persons/:keyword" Method="GET" Call="REST.Person:getperson" Cors="true" /><Route Url="/persons2/" Method="POST" Call="REST.Person:getperson2"/>Routes>}
設定詳細については以下ドキュメントをご参照ください。
CORS使用のためのRESTサービスの構成について【IRIS】
CORS使用のためのRESTサービスの構成について
コードサンプルについては、関連トピックをご参照ください。
JQueryでデータをJSON形式で取得する方法