【IRIS/Cache】ネームスペースどう切り替える?

本記事は、ネームスペースの切り替えについて解説したいと思います。

※この記事は下記の方向けになります。
  • IRIS/Cacheの初心者の方
  • プロセス内でネームスペースを切り替える必要がある方

はじめに

ObjectScriptでネームスペースの切り替えが分らない方はいないと思いますが、どうやって切り替えていますか?

私が知りうる限りでは、ネームスペースを切り替えるコマンドは4種あります。

ネームスペース切り替えコマンド
  • znspace(zn)
  • $zu(5,[namespace名])
  • $znspace
  • $namespace


 ※似たような奴が多いな!

この記事では、これらのコマンドをどのようなタイミングで運用すればいいのか、備忘を兼ねて検証したいと思います。

それではさっそく、ObjectScriptでのネームスペース切り替えについてみていきましょう!

各性能

検証する前に、ネームスペース切り替え時に関連するコマンド達を確認したいと思います。

切り替え時に併せて利用するコマンド

ネームスペースを切り替える際に必要なコマンドをまとめました。

現在のネームスペースを取得する

ネームスペースの切り替えの前に、現在のネームスペースを取得するコマンドになります。
4種記載していますが、「$namespace」を使っておけば十分だと思います。

w $namespace // 現在のネームスペースが返る

w $SYSTEM.SYS.NameSpace()

w $znspace

w ##class(%SYS.ProcessQuery).%OpenId($JOB).NameSpaceGet()

ネームスペースが存在しているか確認する

変更先のネームスペースが存在しているか確認するコマンドになります。
$zuはレガシーなので、%SYS.Namespace.clsの関数を使用する方が良いです。

s ns = $namespace

w ##class(%SYS.Namespace).Exists(ns) // 1 が返る

w $zu(90, 10, ns) // 1 が返る

ネームスペースのリストを取得する

現在のプロセスで使用できるネームスペースの一覧を取得するコマンドになります。
 →ListAll()で十分ですね。

// 方法1
d ##class(%SYS.Namespace).ListAll(.nsList)
zw nsList
// nsList("%SYS")=""
// ~ 略 ~
// nsList("USER")=""

// 方法2
s stmt=##class(%SQL.Statement).%New()
d stmt.%PrepareClassQuery("%SYS.Namespace","List")
s rset= stmt.%Execute(ListRemote)
while(rset.%Next()){ w rset.%Get("Nsp"),",",rset.%Get("Status"),",",rset.%Get("Remote"),!}
// %SYS,1,0
// ~ 略 ~
// USER,1,0

切り替えコマンド

いよいよネームスペースの切り替えコマンドです。

$namespace

$namespaceを「new」した後、$namespaceに変更後のネームスペース名をセットします。

これを行うことで、スタック・レベル内でのみネームスペース変更が有効になります。
 ※ラベル「Move」や関数「Sub」の処理内のみ有効となる

そのため、元の処理に戻った際にネームスペースを戻す処理が不要になります。

ClassMethod main()
{
	s ^nsDt(1, "start")=1 // 実行ネームスペース
	d ..Sub()
	s ^nsDt(3, "Sub after")=1 // 実行ネームスペース
	
	d Move
	s ^nsDt(99, "end")=1 // 実行ネームスペース
	q
Move
	// ネームスペース切り替え処理
	new $namespace
	s $namespace = "USER"
	s ^nsDt(4, "sub")=1 // USERネームスペース
	q
}

ClassMethod Sub()
{
	// ネームスペース切り替え処理
	new $namespace
	s $namespace = "USER"
	s ^nsDt(2, "sub")=1 // USERネームスペース
}

上記を実行すると、各ネームスペースは下記グローバルが格納されます。

実行ネームスペース
^nsDt(1, “start”) = 1
^nsDt(3, “Sub after”) = 1
^nsDt(99, “end”) = 1

ネームスペース「USER」
^nsDt(2, “sub”) = 1
^nsDt(4, “sub”) = 1

ラベル内や関数内での処理のみ、別のネームスペースに書き込まれている事が確認できます。
仮にスタック内でエラーが発生しても、元の処理に影響がないのが良いです。

znspace(zn)

ターミナルでネームスペースを切り替える際によく利用していると思います。
ネームスペース切り替えでは、一番メジャーなコマンドですよね。

この「znspace(zn)」コマンドは$namespaceと異なり、一度切り替えたらそのネームスペースを維持し続けます。

そのため、元のネームスペースに戻るときは、再度切り替え処理を実行する必要があります。

ClassMethod main()
{
	s ^nsDt(1, "start")=1 // 実行ネームスペース
	d ..Sub()
	s ^nsDt(3, "Sub after")=1 // USERネームスペース
	
	zn "sample"
	d Move
	s ^nsDt(99, "end")=1 // USERネームスペース
	q
Move
	// ネームスペース切り替え処理 
	zn "USER"
	s ^nsDt(4, "sub")=1 // USERネームスペース
}

ClassMethod Sub()
{
	// ネームスペース切り替え処理
	zn "USER"
	s ^nsDt(2, "sub")=1 // USERネームスペース
}

上記を実行すると、各ネームスペースは下記グローバルが格納されます。

実行ネームスペース
^nsDt(1, “start”) = 1

ネームスペース「USER」
^nsDt(2, “sub”) = 1
^nsDt(3, “Sub after”) = 1
^nsDt(4, “sub”) = 1
^nsDt(99, “end”) = 1

znspace(zn)は、一度切り替えると元に戻らない為、全てネームスペース「USER」に書き込まれている事が確認できました。

下記コマンドも、znspaceと同様の動作を行います。

s $znspace = "USER"
d $zu(5,"USER")

使い分け

ドキュメントにも記載されていますが、一連の処理の流れでネームスペースを切り替えるのであれば、「new $namespace」が使い勝手が良いです。
何より、ネームスペースの切り替え漏れによる事故を防ぐ事ができるのが良いです。

ターミナルでの切り替えであれば、圧倒的にタイピング数が減る「zn」一択ですね。

%SYS.Namespace備忘録

冒頭で少しだけ触れた「%SYS.Namespace.cls」に関する、他の関数を備忘的に記載します。
詳細はドキュメントを確認していただけると助かります。

GetAllNSInfo

デフォルトのグローバル データベースとルーチン データベースに関する情報を返す。
 →Get All NameSpace Infoの略ですかね

k info
d ##class(%SYS.Namespace).GetAllNSInfo("sample", .info)
zw info

// 下記が出力される
// info("GlobalDB","Directory")="d:\irisdb\sample-data\"
// info("GlobalDB","Mounted")=1
// info("GlobalDB","ReadOnly")=0
// info("GlobalDB","Resource")="%DB_%DEFAULT"
// info("GlobalDB","Status")=1
// info("GlobalDB","System")=""
// info("RoutineDB","Directory")="d:\irisdb\sample\"
// info("RoutineDB","Mounted")=1
// info("RoutineDB","ReadOnly")=0
// info("RoutineDB","Resource")="%DB_%DEFAULT"
// info("RoutineDB","Status")=1
// info("RoutineDB","System")=""

GetNSInfo

デフォルトのグローバル データベースに関する情報を返す。

k info
d ##class(%SYS.Namespace).GetNSInfo("sample", .info)
zw info

// 下記が出力される
// info("Directory")="d:\irisdb\sample-data\"
// info("Mounted")=1
// info("ReadOnly")=0
// info("Resource")="%DB_%DEFAULT"
// info("Status")=1
// info("System")=""

GetGlobalDest

指定したグローバルに対し、マッピングDBのディレクトリを返す。

s gblNm = "^nsDt"
w ##class(%SYS.Namespace).GetGlobalDest("sample","^nsDt")
// ^d:\irisdb\sample-data\ を返す

s gblNm = "^developer.data.Defrag4D"
w ##class(%SYS.Namespace).GetGlobalDest("sample","^nsDt")
// ^d:\irisdb\test64\ を返す

GetPackageDest

指定したパッケージに対し、マッピングDBのディレクトリを返す。

s pgNm = "HS"
w ##class(%SYS.Namespace).GetPackageDest("sample", pgNm)
// ^d:\iris\mgr\hslib\ を返す

GetRoutineDest

指定したルーチンに対し、マッピングDBのディレクトリを返す。

s rtnNm = "HSMOD.*"
w ##class(%SYS.Namespace).GetRoutineDest("sample", rtnNm)
// ^d:\iris\mgr\hslib\ を返す

おわりに

この記事では、ネームスペース切り替えについて、その基本手順や注意点、効率的な活用方法をお伝えしました。

業務の中でネームスペースの切り替えを行う機会は、そう多くはないかもしれません。
しかし、必要なときにスムーズに対応できるよう、ぜひ頭の片隅に留めておいていただければ幸いです。