クラスの中で配列プロパティを使い、その要素 (キーと値の両方) によってスピーディに検索を実行できると非常に便利な場合があります (EAV モデルの場合は特に重宝します)。
それでは、簡単な例を見てみましょう。
InterSystems ObjectScriptは、InterSystemsデータプラットフォームの任意のデータモデル(オブジェクト、リレーショナル、Key-Value、ドキュメント、グローバル)を使用してデータを操作し、InterSystemsデータプラットフォーム上のサーバーサイドアプリケーションのビジネスロジックを開発するためのスクリプト言語です。 ドキュメント
クラスの中で配列プロパティを使い、その要素 (キーと値の両方) によってスピーディに検索を実行できると非常に便利な場合があります (EAV モデルの場合は特に重宝します)。
それでは、簡単な例を見てみましょう。
これは InterSystems FAQ サイトの記事です。
クラスに定義されたプロパティの情報については、以下システムクラスを利用して情報を取得できます。
%Dictionary.PropertyDefinition
コード記述例は以下の通りです。
Class ISJ.Sample
{
ClassMethod getPropInfo(classname As %String)
{
set cls=##class(%Dictionary.ClassDefinition).%OpenId(classname,,.status)
if $$$ISERR(status) {
write "指定クラスは存在しません",!
quit // または return
}
set x=cls.Properties
for i=1:1:x.Count() {
// プロパティ情報を取得(%Dictionary.PropertyDefinition)
set prop=x.GetAt(i)
if prop="" {
continue
}
set propname=prop.Name // プロパティ名
set proptype=prop.Type // プロパティタイプ
if propname="" {
continue
}
write propname," ",proptype,!
}
}
}(1NF/2NF/3NF)露 からの引用
行と列で特定される位置には、それぞれアプリケーションドメインの値が 1 つだけあります (それ以外は何もない)。 その目的によって、同じ値がアトミックであったり、なかったりします。 例えば、「4286」という値は、
- 「クレジットカードの PIN コード」を意味するのであれば、アトミックとなります (破損している場合や並び替えられている場合は、使用できません)。
- 単に「連続する番号」であれば、非アトミックとなります (いくつかに分割されていたり、並び替えられていても、値は意味を成します)。
この記事では、文字列や日付、($LB 形式の) 単純なリスト、「list of <...>」、「array of <...>」といったフィールドの型を伴う SQL クエリのパフォーマンスを向上させる標準的な方法にして検証します。
これは InterSystems FAQ サイトの記事です。
グローバル変数毎のデータベースキャッシュ使用量を確認するツール(^GLOBUFFユーティリティ)が用意されています。
%SYSネームスペースにて、ユーティリティを直接実行する方法と、プログラムで実行する方法があります。
ユーティリティを直接実行する方法は以下のようになります。
これは InterSystems FAQ サイトの記事です。
引数名の後ろに ... をつけることで可変の引数を渡すことができます。
ObjectScript では、配列を使って任意の数の引数を渡すことができます。
例文は以下の通りです。
例文では、メソッド実行後に確認しやすいように、グローバル変数(=データベースに格納される変数)に引数の情報を設定しています。
Class TEST.ARGTEST1 Extends %RegisteredObject
{
ClassMethod NewMethod1(Arg... As %String) As %Boolean
{
kill ^a
merge ^a = Arg
}
}ターミナルで実行した結果は以下の通りです。
USER>DO ##class(TEST.ARGTEST1).NewMethod1(1,2,3,4,5)
USER>ZWRITE ^a
^a=5
^a(1)=1
^a(2)=2
^a(3)=3
^a(4)=4
^a(5)=5これは InterSystems FAQ サイトの記事です。
ファイル入出力処理を行うには、ライブラリクラスを利用する方法が便利です。
ライブラリクラスを使用する以外には、Open/Use/Close コマンドを使用する方法もあります。<※1>
ファイル入出力処理には、%Library.Fileクラス、%Stream.FileCharacter/%Stream.FileBinary を使用します。
簡易例やプロパティ/メソッド詳細は、以下ドキュメントをご参照ください<※2>。
クラスリファレンス【IRIS】
クラスリファレンス
【補足】
%Libraryパッケージは、クラス定義構築基盤として利用するクラスが多いためパッケージ名を省略することができます。
(%Library.File は %File として利用できます)
【A】%Fileクラスを利用する方法
%Fileクラスには、ファイル入出力操作の他に、ディレクトリ作成(CreateDirectory()など)/存在チェック(Exists())/OS非依存でファイルパス取得(NormalizeFilename()など)が行える様々な便利メソッドを用意しています。
ファイル出力処理手順は以下の通りです。
(1) ファイル用オブジェクトを作成
ファイル名をフルパスで指定しながらファイル用オブジェクトを作成します。
set##class%FileWebで行われるサーバーとクライアント間のほとんどの通信は、リクエストとレスポンスの構造に基づいており、 クライアントがサーバーにリクエストを送信すると、サーバーがそのリクエストに対するレスポンスを送信します。 WebSocketプロトコルは、サーバーとクライアント間の双方向通信チャンネルを提供するプロトコルで、サーバーがリクエストを受信しなくても、クライアントにメッセージを送信することができます。 WebSocketプロトコルと、InterSystems IRISでの実装についての詳細は、以下のリンクをご覧ください。
このチュートリアルは、「非同期WebSocket -- クイックチュートリアル」を、Caché 2016.2以上とInterSystems IRIS 2018.1以上向けに更新したものです。
InterSystems IRISでは、WebSocket接続を同期的または非同期的に実装することができます。 クライアントとサーバー間のWebSocket接続がどのように動作するかは、%CSP.WebSocketクラスの「SharedConnection」プロパティによって決まります。
こんにちは、皆さま。
業務でIRISを用いて開発を行っている者です。
ObjectScriptでは様々な型の変数定義が可能ですが、
実際に定義された変数(Object)から、その変数の型を逆引きする方法を
ご存じな方はいらっしゃいませんでしょうか?
理想としては、Java等で利用可能な『instanceof』演算子の
代替えとなるような仕組みが望ましいです。
力技で何とかなりそうなら、専用のメソッドみたいなものを
自作で作ってもよいかなとは考えておりますが、
現状その力技すら思いついていない状況です。。。
何か情報をお持ちの方がいらしたら、助言いただけますと幸いです。
これは InterSystems FAQ サイトの記事です。
^%GSIZE ユーティリティでは、グローバルのサイズを算出することができます。
このユーティリティで出力される各項目の意味について説明します。
例えば、USERネームスペースのグローバルについて do ^%GSIZE を実行し、以下のように出力結果を得られたとします。
これは InterSystems FAQ サイト の記事です。
以下のサンプルでは、画像ファイルをクラスプロパティにBase64文字列にエンコードして保存し、再びそれをBase64でデコードし、別のファイルに復元しています。
【使用クラス】
Class User.test Extends %Persistent
{
Property pics As %GlobalBinaryStream;
}
【取込み時】
set x=##class(User.test).%New() // ここに保存
// 画像準備
set file=##class(%File).%New("c:\temp\Mii.png")
do file.Open("RUK\BIN\")
for {
if file.AtEnd=1 quit
// 画像を1024 byteずつ Base64形式に変換(エンコード)
set cnt=file.Read(1024)
set b64=$system.Encryption.Base64Encode(cnt) // b64: 1402byte
do x.pics.Write(b64)
}
do x.%Save()
do file.Close()これは InterSystems FAQ サイトの記事です。
ダイナミックオブジェクトから JSON 文字列を生成するときに使用する %ToJSON() の引数にストリームオブジェクトを指定することでエラーを回避できます。
コード例は以下の通りです。
USER>set temp=##class(%Stream.TmpCharacter).%New()
USER>set jsonobj={}
USER>set jsonobj.pro1=["a","b","c","d"]
USER>set jsonobj.pro2=["あ","い","う","え"]
USER>do jsonobj.%ToJSON(temp)
USER>write temp.Size
51
USER>write temp.Read()
{"pro1":["a","b","c","d"],"pro2":["あ","い","う","え"]}詳細はドキュメントもご参照下さい。
開発者の皆さん
こんにちは。
Windows共有しているリモートサーバに出力されたファイルでデータ連携する際、セキュリティ上、資格情報が必要となるケースが良くあるかと思います。いままでCachéで連携していた時には%ZSTARTルーチンや常駐プロセスのルーチンにて「net useコマンド」を実行されていたかと思いますが、IRISではInteroperability機能が使用できますので、前回の記事で作成したビジネスサービスクラスを元に、資格情報を使ってWindows共有フォルダにアクセスできる機能を追加したいと思います。
ビジネスサービスが起動、停止する際に呼び出されるOnInit()、OnTearDown()メソッドにnet useコマンドを埋め込み、指定されている資格情報を使ってnet useコマンドで共有フォルダへの接続、切断を行います。
ビジネスサービスの設定画面で認証情報を選択できるよう、以下のようにCredentialsプロパティ、SETTINGSパラメータをTest.BS.ImportMasterクラスに設定します。
皆さん、こんにちは。
他のシステムとファイル連携を行う場合、Cachéでは、Jobコマンドを使った常駐プロセスやタスクを作成し、特定のディレクトリにあるファイルを定期的に監視、データを取り込むといった機能を手作りされていたかと思います。
これにはファイルの監視や、常駐プロセスの監視、プロセスの制御(起動、停止)を行う機能を用意する必要がありましたが、IRISではInteroperability機能が使えますので、そのようなプログラムを省略することが可能です。
今回は、既にファイル読込処理を行うルーチンが存在し、ルーチン呼出時の引数にファイル名があるという前提で、その処理をInteroperability機能を使ってどのように呼び出すかについて説明したいと思います。
作業手順は以下の通りとなります。
スタジオを起動し、ファイル読込処理を行うルーチンが存在するネームスペースに接続します。
「ファイル」「新規作成」メニューをクリックします。
以下のダイアログボックスが表示されますので、「プロダクション」カテゴリをクリックし「ビジネスサービス」アイコンをクリック、「OK」ボタンをクリックします。

開発者の皆さん、こんにちは!
VSCode の ObjectScript エクステンションで、プロセスにアタッチしてデバッグする方法についてご紹介します。
ObjectScript エクステンションの基本的な操作方法については、こちらの記事をぜひご参照ください。
解説ビデオ(4分ちょっと)もあります。ぜひご参照ください。
VSCode のデバッグ実行に関連する各種の構成情報を記述するための launch.json に ObjectScript エクステンション用の設定を記述します。
.png)
(ビデオだと、最初~1:31 で解説しています)
プロセスにアタッチするデバッグ設定例は以下の通りです。
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "objectscript",
"request":"attach",
"name": "Debugテスト",
"processId":"${command:PickProcess}",
"system": true
}
]
}これは InterSystems FAQ サイトの記事です。
以下例のクラスメソッド getLatestID() のように ObjectScript のクラスメソッドを用意します。
返したい値を戻り値に指定し、SQLストアドプロシージャ(SqlProc)キーワードを指定するだけで値が返せます。
ClassMethod getLatestID() As %Integer [ SqlName = getLatestID, SqlProc ]
{
set latestID=$Order(^ISJ.TestClass1D(""),-1)
quit latestID
}操作を試す場合は、以下のクラス定義をご準備ください。
Class ISJ.TestClass1 Extends (%Persistent, %Populate)
{
Property name As %String;
ClassMethod getLatestID() As %Integer [ SqlName = getLatestID, SqlProc ]
{
set latestID=$Order(^ISJ.TestClass1D(""),-1)
quit latestID
}
}これは InterSystems FAQ サイトの記事です。
XMLファイルの内容を格納する永続クラス定義を作成し、%XML.Adaptor を追加で継承します。
例は以下の通りです(右端の %XML.Adaptorクラスを追加で継承します)。
Class ISJ.Class1 Extends (%Persistent, %Populate, %XML.Adaptor次に、%XML.Reader クラスを使用して格納先のインスタンスへ、タグとクラスの関連付け(Correlate())を行い、reader.Next() でXMLを取り込みます。
set sc=reader.OpenFile(filename)
do reader.Correlate(tag,class)
while reader.Next(.x,.sc) { do x.%Save() } サンプルコードは以下の通りです。
Class ISJ.Class1 Extends (%Persistent, %Populate, %XML.Adaptor)
{
Property a As %String;
Property b As %String;
/// 引数:入力するXMLファイルのフルパス
ClassMethod Import(filename As %String)
{
if $get(filename)="" {
write "入力ファイルを引数に指定してください",!
quit
}
// クラス名指定(..%ClassName()でクラスメソッドの存在するクラス名を返します)
set class=..%ClassName(1)
// XMLタグ指定
set tag="test"
set reader = ##class(%XML.Reader).%New()
set sc=reader.OpenFile(filename)
If $$$ISERR(sc) {
write $system.Status.GetErrorText(sc),!
Quit
}
// クラスとの関連付け
do reader.Correlate(tag,class)
while reader.Next(.x,.sc) {
set sc=x.%Save()
If $$$ISERR(sc) {
write $system.Status.GetErrorText(sc),!
Quit
}
}
quit
}
}これは InterSystems FAQ サイトの記事です。
Java ゲートウェイを使用することで、Java クラスのモジュールを InterSystems IRIS から実行できます。
【メモ】Java ゲートウェイは、外部 Java オブジェクトを InterSystems IRIS 内のネイティブ・オブジェクトと同じようにインスタンス化し、Javaオブジェクトを操作するための方法です。
詳細は以下ドキュメントをご参照ください。
Java ゲートウェイについて
Java ゲートウェイを使用する手順は以下の通りです。
1) Java ゲートウェイサーバを開始する
2) プロキシオブジェクト(ダイナミック・プロキシ・オブジェクト)を作成して Java オブジェクトを操作する
Java ゲートウェイサーバを開始する方法は 3 種類あります。以下のいずれかの方法で、Java ゲートウェイサーバを開始します。
A) 管理ポータルの「オブジェクトゲートウェイ」を利用する
B) プロダクションにJavaゲートウェイサービスを追加する
C) java コマンドを使用する
A)~C) の方法は以下の通りです。
開発者の皆さん、こんにちは!
InterSystems ObjectScript でライブラリやツール、パッケージなどを開発していると、「このパッケージはどうすればターゲットマシンに展開できるのか?」という疑問がよく浮かびます。
また、私たちは、既に別のライブラリがインストールされていることを想定したり、その特定のバージョンのことを考慮したりしながらパッケージを開発しています。
JavaScript や Python などでコーディングを行うと、依存関係を管理しながらパッケージを展開するのに パッケージ管理システム が必要になります。
これを踏まえ、 InterSystems ObjectScript Package Manager のリリースを発表したいと思います!
これは InterSystems FAQ サイトの記事です。
$IsObject()を使用して判別できます。 調べたい変数をvとすると、
となります。
vが未定義の場合は、$IsObject(v)はUNDEFINEDエラーとなりますので、ご注意ください。
UNDEFINEDエラーを防止するには、次のように$Getを使用することをお勧めします。
皆さんこんにちは。
以下のメソッドでは日付の入った配列を受け取り、すべてのYYYY-MM-DD形式の
日付を$horologに変換しているのですが、たまに日付が古すぎるものが入っており
<VALUE OUT OF RANGE>エラーが発生して途中で止まってしまいます。
エラー時にエラーメッセージを代入してそのまま継続できる方法はないでしょうか?
プログラムは以下の通りです。
Class DC.Sample Extends %RegisteredObject [ Language = objectscript ]
{
/// 配列に入っているYYYY-MM-DD形式の日付を$horologに変換する
ClassMethod TransDate(array) As %Status
{
set key="" for {
set key=$order(array(key),1,data)
quit:key=""
set array(key)=$zdh(data,3)
}
quit $$$OK
}
}よろしくお願いいたします。
これは InterSystems FAQ サイトの記事です。
InterSystems ObjectScript言語では引数の異なる同名のメソッドを定義することはできません。
InterSystems ObjectScript言語は一般的に動的言語と呼ばれるプログラミング言語に分類されます。
ObjectScriptではメソッド実行時にどの引数を使用するかどうかは自由に制御可能ですので、動的プログラミング言語ではないJava等の言語と異なり、コンパイルの段階で厳密に引数の数でメソッドを区別する必要がありません。
従って ObjectScript言語は、オーバーロードと一般に呼ばれる言語仕様を含んでいません。
Java等で記述されたプログラムを移植する際にオーバーロード相当の機能を実現するには、
ClassMethod test(args... as %String)
のように引数の後ろに ... を付加します。
これにより、可変長引数を渡すことが可能です。
このメソッドに複数の引数が渡された場合は、args(1)=第一引数 args(2)=第二引数というように順次設定されます。
これを使用して、メソッドコード中で渡された引数の個数を取得して処理を分岐させることができます。
※ただし、引数のデータタイプを判別することはできません。
これは InterSystems FAQ サイトの記事です。
$ZSTRIP() 関数を使用します。
この関数を使用すると、指定文字列から、文字のタイプと文字を削除できます。
下記の例のように、第2引数で、"<"、">"、"<>"を指定することにより、SQLのLTRIM、RTRIM、TRIM関数と同等の処理が可能になります。
前回の記事では、データの変更を簡単に記録できる方法をお見せしました。 今回は、監査ログが記録されるデータ構造と監査データを記録する「Audit Abstract クラス」を変更しました。
また、データ構造は親構造と子構造に変更し、それぞれに「トランザクション」とそのトランザクションで「その値によって変更されたフィールド」を記録するテーブルが 2 つ設けられます。
新しいデータモデルをご覧ください。
「監査クラス」から変更したコードをご覧ください。
開発者の皆さん、こんにちは!
第9回のマルチモデルコンテストの 続報 📣 の「テクノロジーボーナス」についてご紹介します。
詳細は以下ご参照ください。
InterSystems グローバルは、InterSystems IRIS に任意のデータを格納するために使用される多次元スパース配列です。
各グローバル・ノードはキーとみなされ、値(バリュー)を設定することができます。InterSystems IRIS は、グローバルを管理するための ObjectScript のコマンドや Native API を含む一連の API を提供しています。
ObjectScript または Native API を介してグローバルを使用すると、2 ポイント獲得できます。
多くのアプリケーションに共通する要件は、データベース内のデータ変更のログ記録です。どのデータが変更されたか、誰がいつ変更したかをログに記録する必要があります(監査ログ)。 このような質問について書かれた記事は多く存在し、Caché で行う方法の切り口もさまざまです。
そこで、データ変更を追跡して記録するためのフレームワークを実装しやすくする仕組みを説明することにします。 これは、永続クラスが「監査抽象クラス」(Sample.AuditBase)から継承すると「objectgenarator」メソッドを介してトリガーを作成する仕組みです。 永続クラスは Sample.AuditBase から継承されるため、永続クラスをコンパイルすると、変更を監査するためのトリガーが自動的に生成されます。
次は、変更が記録されるクラスです。
$LIST のフォーマットと%DynamicArray、%DynamicObject クラス
IRIS には、様々なデータ値を含むシーケンスを作成する方法がいくつかあります (以前は Cache にもありました)。 長年に渡り使用されているデータシーケンスの 1 つに $LIST の文字列があります。 より最近のデータシーケンスには %DynamicArray クラスと %DynamicObject クラスがあり、両者ともに JSON の文字列表現に対応する IRIS サポートの一部となっています。 これら 2 つのシーケンスにはそれぞれ非常に異なるトレードオフがあります。
$LIST の文字列形式
$LIST 形式は、かつてメモリアドレスのスペースが小さいだけでなく、ディスクドライブも小さく、読み取り速度が遅かった時代に考案されました。 $LIST の形式は、複数の異なるデータ型で構成されるシーケンスをバイト数を可能な限り抑えながら 8 ビットの一般的な文字列にパッキングするためにデザインされました。
$LIST のシーケンスは、ObjectScript の $LISTBUILD 関数を使って作成します。
$LIST の文字列の最も重要な機能は、データを 8 ビットの値で構成される最小のシーケンスにぎっしりパッキングできるという点です。
これはInterSystems FAQ サイトの記事です。
InterSystems OpenExchangeのVS Code用のプラグインを利用することでVS Code上でクラス定義の編集が可能です。
(今後は、AtelierではなくVS Codeの使用を推奨しています。)
詳細は、以下ページをご参照ください。
また、逆にテーブル定義からクラス定義を生成することも可能です。
方法①として、他社RDBMS用に作成したDDL文をインターシステムズ製品上で実行、またはインポートする方法があります。
詳細は、以下ドキュメントをご参照ください。
方法②として、クラス定義クラス・%Dictionary.ClassDefinitionで定義されているAPIを利用し、プログラミングにより操作する方法があります。
クラス定義クラスは、システムクラスであり、スタジオや他のエディターで作成されたクラスは全てこのシステムクラスを使いクラスディクショナリに定義情報が格納されています。
このクラス詳細については、以下ドキュメントをご参照ください。
皆さん、こんにちは。
ストリームデータをデータベースに格納する場合、ファイルなどから読み取る際に漢字コード変換を行い、Unicode形式で%GlobalCharacterStreamに格納されるかと思いますが、時々、バイナリのままで読み込んでしまい、漢字コード変換を行わないといけない状況があるかと思います。
ファイルストリームでしたら%FileCharacterStreamクラスのTranslateTableプロパティに元の漢字コードを指定すれば、以下のようにコード変換しながら読みだすことは可能です。
変数binは%FileBinaryStreamクラスのインスタンス USER>zzdump bin.Read() 0000: E6 97 A5 E6 9C AC E8 AA 9E E3 82 92 E5 90 AB E3 æ.¥æ.¬èª.ã..å.«ã 0010: 82 80 E6 96 87 E5 AD 97 E5 88 97 E3 81 8C E3 81 ..æ..å.å..ã..ã. 0020: A9 E3 81 AE E3 82 88 E3 81 86 E3 81 AB E8 A1 A8 ©ã.®ã..ã..ã.«è¡¨ 0030: E7 A4 BA E3 81 95 E3 82 8C E3 82 8B E3 81 8B E3 示ã..ã..ã..ã..ã 0040: 82 92 E3 83 81 E3 82 A7 E3 83 83 E3 82 AF E3 81 ..ã..ã.§ã..ã.¯ã. 0050: 97 E3 81 A6 E3 81 84 E3 81 BE E3 81 99 0D 0A .ã.¦ã..ã.¾ã.... USER>do bin.Rewind() 1 USER>set stream=##class(%FileCharacterStream).%New() USER>set stream.Filename=bin.Filename <--- ストリームデータを保持しているファイルのファイル名をコピー USER>set stream.TranslateTable="UTF8" <-- UTF-8形式のデータを読み込む USER>write stream.ReadLine() 日本語を含む文字列がどのように表示されるかをチェックしています USER>
これは、InterSystems FAQサイトの記事です。
以下の例では Test.Class2 クラスの Images プロパティに画像ファイルが保存できるように定義しています。
input() メソッドを利用して画像ファイルを Images プロパティに登録し、データベースに保存したとします。
Class Test.Class2 Extends /// 以下Storage定義は省略}
データベース登録されたストリームデータを画像ファイルに出力するコード例は以下の通りです(ID=1で格納されたデータをオープンしています)。