ベータ公開されている18 R5では,エンティティセレクションの実装が変わり,デフォルトで共有オブジェクト版のエンティティセレクションが作成されるようになりました。共有エンティティセレクションは,新規プロセスまたはワーカーにパラメーターとして渡すことができます。
仕様の変更に伴い,query()やall()のようなメソッドから返されたエンティティセレクションに対してentitySelection.add()を使用した場合,エラー1637が返されることになりました。共有エンティティセレクションは,リードオンリーだからです。まず,エンティティセレクションをコピーし,共有オブジェクトではないエンティティセレクションを作成してから,エンティティを追加する必要があります。
仕様が変更されたのは,ORDAコーディングの特性に関する理解が進み,将来を見越した最適化が図られたためです。
注記: ベータ版の情報です。リリース版では仕様が変更される可能性があります。
大抵のORDAアプリケーションでは,エンティティセレクションを作成した後,or() minus() and()のような「セット演算」に使用したり,query() slice() orderBy() のような「フィルター」で絞り込んだりするようなロジックが一般的です。列挙したメソッドは,いずれも新規エンティティセレクションを返し,元のエンティティセレクションは変更しません。別の言い方をすれば,オブジェクトとしてのエンティティセレクションはミュータブル(変更不可)です。
たとえば
$es:=ds.Company.query(…).orderBy(…).minus(…)
というコードは,3段階にわたってエンティティセレクションを絞り込んでいますが,その都度,返されたエンティティセレクションに基づいて新しいエンティティセレクションを作成しているのであり,単一のエンティティセレクションを縮小しているわけではありません。ドット記法を連鎖せずに書き換えれば,その点が明確になります。
$es1:=ds.Company.query(…)
$es2:=$es1.orderBy(…)
$es3:=$es2:.minus(…)
このようなクエリ処理であれば,エンティティセレクションがリードオンリーであっても実行できることに注目してください。
add()は,元のエンティティセレクションを変更する例外的なメソッドです。ORDAでユーザーインタフェースを実装するような場合に使用します。リードオンリーのエンティティセレクションにエンティティを追加することはできないので,OB CopyあるいはentitySelection.copy()であらかじめ共有ではないエンティティセレクションを作成しておき,リストボックス等のデータソースに設定するのがポイントです。
Form.company:=ds.Company.query(…).copy()
Form.company.add(…)
Form.company.add(…)
つまり,18 R5以降,ユーザーインタフェースに表示するエンティティセレクション,特に内容を更新する可能性があるエンティティセレクションは,all()やquery()で作成した後,仕上げにcopy()を実行する,というコーディングになります。
エンティティセレクションを作成するコマンドは,いずれも共有オブジェクトを返しますが,Create entity selectionだけは例外です。このコマンドは,共有エンティティセレクションを作成し,その参照を返すわけではありません。そうではなく,クラシックコードで作成された既存のカレントセレクションに対するエンティティセレクション型の参照を作成し,その参照を返します。元となったカレントセレクションをREDUCE SELECTIONした場合,対応するエンティティセレクションもリサイズされるのはそのためです。
ドキュメントの記述は「新規エンティティセレクションを返します」となっていますが,前述したように,新規に作成されるのは,エンティティセレクション型のオブジェクトであり,エンティティセレクションそのものではありません。この振る舞いは,命名セレクションからカレントセレクションを「作成」するUSE NAMED SELECTIONに似ています。
エンティティセレクションは,オブジェクトの参照なので,変更不可ということに決めれば,実体の代わりに参照を複製するだけで済みます。100万件の順列なしエンティティセレクションの実体は,100キロビットのスペースを占有することがあります。順列ありのエンティティセレクションであれば,エンティティ1個につき,4バイトです。共有エンティティセレクションの参照であれば,エンティティ数に関係なく,サイズはわずか8バイトで済みます。
プロセス間で受け渡しができるといっても,すぐには共有エンティティセレクションの効果的な用途が思い浮かばないかもしれません。4D Remoteのクライアントであれば,DIALOGコマンドの*オプションやFormオブジェクトを活用することにより,アプリケーションプロセスだけでユーザーインタフェースを実装することができます。そのため,別プロセスにエンティティセレクションを渡して処理するようなことは限定的です(集計処理など)。
共有エンティティセレクションは,将来を見越した仕様です。現在,どのプロセスからでもアクセスできるStorageという共有オブジェクトがあり,プロセス間でオブジェクトを共有することができますが,同じように,Webリクエスト間で共有できるSessionオブジェクトの開発が進められています。これが実現すれば,Webリクエスト間でエンティティセレクションを共有できるようになります。Webクライアント(ブラウザ)は,ひとつのセッションで多数のプロセスを使用し,サーバーと非同期でプリエンプティブに通信するので,エンティティセレクションをコピーする代わりに参照を使用すれば,メモリとCPUの負担が大幅に軽減できる,と期待されています。
詳細は4D Forumsで読むことができます。
タブコントールオブジェクトのデータソースは配列またはリスト(倍長整数)にすることができます。リストを使用する場合,オブジェクトの変数はOn Loadイベントではなく,フォームを開く前に宣言されていなければなりません。オブジェクトの変数を宣言しないのであれば,オブジェクトのプロパティリストで変数タイプが「数値」に設定されている必要があります。タブコントロールの変数は,デフォルトでテキスト配列となります。データソースが数値型でない場合,タブコントールを対象にSelected list itemsなどのリスト系コマンドは使用できません。これは仕様です。
DOM Parse XML variableには,テキスト型またはBLOB型の変数またはフィールドを渡す必要があります。オブジェクト型のプロパティ,たとえば$obj.dataのようなテキスト値を渡すことはできません。これは仕様です。ランゲージの設計上,変数と値には違いがあり,値を受け取るコマンドに変数を渡すことはできますが,その逆はできません。似たような例としてValue typeには値を渡すことができますが,Typeには変数またはフィールドしか渡せません。変数と値には違いがある,という点に留意してください。
パラメーター型を宣言する新しいvarシンタックスでは,暗黙的に任意のパラメーターを宣言することができません。つまり,C_VARIANT($0;${1})"のようなことができません。これは仕様です。パラメーター数が事前に決まっていない場合,コレクション側を使用することを検討してください。
プロジェクトモードでは,フォームのタイプによって保存されるプロパティに違いがあります。これは仕様です。詳細フォーム(スクリーン用・印刷用)では,フォームの境界だけが保存されます。リストフォーム(スクリーン用・印刷用)では,境界・マーカー・マーカーラベルが保存されます。つまり,詳細フォームにはマーカーのが存在しません。フォームのタイプを後から変更した場合,該当しないプロパティは(プロパティリストに表示されるとしても)保存されませんので注意してください。
On Display Detailフォームイベント中にOBJECT SET COORDINATESでオブジェクトの位置やサイズを変更することはしないでください。この点はドキュメントに明記されています。
Windows版では,画面の描画に使用されているシステムAPIの関係で,実際にはOn Display Detailフォームイベント中にコマンドを使用することができます。しかし,macOSではウィンドウの描画が最適化されているため,同じような振る舞いになりません。
リストの詳細行に配置されたオブジェクトでプログレスバーのようなユーザーインタフェースを実現するのであれば,四角形をリサイズするのではなく,SVGピクチャまたは進捗バーオブジェクトの使用を検討してください。
コンパイラー設計上の制約により,下記のようなコードはコンパイルモードで動作しません。
GET LISTBOX CELL POSITION(Self->;col;row;var)
問題を回避するためには,ポインターの逆参照をローカル変数に代入した上で,パラメーターとして渡すことができます。
$ptr:=Self
GET LISTBOX CELL POSITION($ptr->;col;row;var)
Selfだけでなく,ポインターを返すコマンドの逆参照を直接パラメーターとして渡した場合,正しいコードがコンパイルされません。これは仕様です。