リファレンス
Related information
はじめに
EBX® スクリプトは、EBX カスタマイズ (計算値、テーブルトリガー、スクリプトタスクなど) など、現在 Java が必要なあらゆる場所で使用できるように設計された、シンプルで非常に強力な言語です。
これは DSL (ドメイン固有言語) に基づいています。DSL は手続き型で、強く静的に型付けされた言語です。
スクリプトを記述するには、EBX IDE を使用できます。これは、関数フィールド、テーブルトリガー、スクリプトタスクのスクリプトの定義を支援するツールと機能を提供する統合開発環境です。構文の強調表示、コンテキストコードの補完、ソースのコンパイルと公開などのさまざまな機能を備えたエディターが含まれています。
DMA を使用して新しい機能フィールドまたはテーブルトリガーを作成すると、EBX® Script IDE にデフォルトのスクリプトが作成されます。
EBX® Script IDE を使用してスクリプト タスクを作成すると、ワークフローモデル で指定できます。
字句構造
はじめに
スクリプトの構造は次のとおりです。
<unit usage statement 1>
<unit usage statement 2>
...
<unit usage statement N>
<model usage statement 1>
<model usage statement 2>
...
<model usage statement M>
<function or procedure definition 1>
<function or procedure definition 2>
...
<function or procedure definition M>
次の例は、関数フィールドのスクリプトです。
// This field returns the full address for current record.
export function getValue(): string
begin
var address := _ebx.record.FirstName | ' ' | _ebx.record.LastName;
for street in record.OfficeAddress.Street do
begin
address |= '\n' | street;
end;
address |= '\n' | _ebx.record.OfficeAddress.ZipCode | ' ' | _ebx.record.OfficeAddress.City;
address |= '\n' | _ebx.record.OfficeAddress.Country;
return address;
end
次の例は、テーブルトリガーのスクリプトです。
//This trigger adds the full name of current record.
export procedure onBeforeCreate()
begin
_ebx.record.fullName := _ebx.record.firstName | ' ' | _ebx.record.lastName;
end
文字セット
Unicode 文字セットがサポートされています。
文字の大文字と小文字の区別
DSL では大文字と小文字が区別されます。
コメント
1 行のコメントは、// から現在の行の終わりまで拡張されます。
// This is a comment
if _ebx.record.LastName = 'Doe' then // This is another comment.
return true;
複数行のコメントは /* から始まり、*/ で終わります。
/* This is an example of a multi-line
comment */
if _ebx.record.isActive then
return false;
キーワード
予約済みキーワードは、and、or、not、uses、as、frommodelexport、typeof、tableof、primarykeyof、mutable、immutable、modifiable****unmodifiable、persisted****function、procedure、const、var、if、then、else、for、while、in、do、begin、end、return、true、false、raise、null です。
予約済みのキーワードは、プレーンな (引用符で囲まれていない) 識別子として使用することはできません。
識別子
引用符なしの識別子
引用符なしの識別子 は、文字、数字、またはアンダースコア (\_) の無制限の長さのシーケンスです。最初の文字は、文字またはアンダースコアにする必要があります。
有効な文字は a から z および A から Z です。有効な数字は 0 から 9 です。
引用符なしの識別子は、予約済みのキーワードと等しくない場合があります。
引用符付きの識別子
引用符付き識別子は、二重引用符 (")を除く任意の Unicode 文字の無制限の長さです。
引用符で囲まれた識別子は、二重引用符で囲んで使用する必要があります。
引用符なしの識別子は、二重引用符で囲んで使用できます。これは、識別子 ”a\_name” が a\_name と等しいことを意味します。
引用符付きの識別子は予約済みのキーワードにすることができます。
参照
データモデルへの参照
スクリプトはデータモデルへの参照を宣言できます。
XSD ファイルとして展開されたデータモデルの場合、サポートされる構文は次のとおりです。
references model short_name from module module_name as alias;
references model short_name from module module_name;
references model file_path from module module_name as alias;
短縮名は、パスと拡張子を除いたファイル名です。たとえば、 /WEB-INF/ebx/schemas/Directory.xsd の短縮名は Directory です。
エイリアスが指定されていない場合、エイリアスは短い名前またはファイルパスと同じであると見なされます。
次のいずれかの構文を使用して、現在のモジュールからデータモデルを宣言できます。
references model short_name from module . as alias;
references model short_name from module .;
references model file_path from module . as alias;
埋め込みモデルの場合は、次のいずれかの構文を使用します。
references model short_name as alias;
references model short_name;
データモデル参照の例
references model Directory from module "ebx-test" as dic;
references model Directory from module "ebx-test";
references model "/WEB-INF/ebx/schemas/userservice/Directory.xsd" from module "ebx-test" as dic;
references model Directory from module . as dic;
references model Directory from module .;
references model "/WEB-INF/ebx/schemas/userservice/Directory.xsd" from module . as dic;
references model catalog as cat;
references model catalog;
型
定義済みタイプ
次の定義済みタイプがサポートされています。
| タイプ | キーワード | プロパティ | EBX® 対応型 |
|---|---|---|---|
| Boolean | boolean | xs:boolean | |
| Decimal (無制限の精度) | decimal | xs:decimal | |
| Integer (32ビット) | int | xs:int xs:integer | |
| String | string | length (0 以上の整数) | xs:string xs:Name osd:text osd:html osd:email osd:password 1 osd:color osd:dataspaceKey osd:datasetName |
| Timestamp (ミリ秒の精度でタイムゾーンなし) | timestamp | year month (1 から 12) day (1 から 31) hour (0 から 23) minute (0 から 59) second (0.000 から 59.999) | xs:dateTime |
| Date (タイムゾーンなし) | date | year month (1 から 12) day (1 から 31) | xs:date |
| Time (ミリ秒の精度) | time | hour (0 から 23) minute (0 から 59) second (0.000 から 59.999) | xs:time |
| Locale | locale | osd:locale | |
| URI (Uniform Resource Identifier) | uri | xs:anyURI | |
| Resource | resource | osd:resource | |
| Dataspace | dataspace | name identifier (先頭に「B」または「V」が付いた名前) isSnapshot (データスペースがスナップショットの場合は true) | |
| Dataset | dataset | name dataspace | |
| Transaction | transaction | dataspace isAllPrivileges (読み取り/書き込みブール型プロパティ) executionInformation (読み取り/書き込み文字列プロパティ) executionTimestamp executionUUIDString |
1 タイプ osd:password の関数フィールドを定義することはできません。
複合型
複合型は、EBX® スキーマで定義されたグループ (複合) ノードの型です。
詳細については、複合型の変数の章を参照してください。
リスト型
DSL はリストをサポートしています。次の構文を使用してリストを宣言します。
list<item_type>
リストはデフォルトでは変更できません。次の構文を使用して変更可能なリストを宣言できます。
modifiable list<item_type>
リストが変更不可の場合、項目を追加、削除、または置換することはできません。
インデックス付き表記を使用して、値を設定または取得します (最初のインデックスは 0)。
// Set first value of cities.
cities[0] := 'Paris';
// Get the second item of cities.
return cities[1];
インデックスは、int 型または 10 進数の任意の式にすることができます。インデックスが 10 進数の場合、小数部分は無視されます。
インデックスが null、負の値、または範囲外の場合、get 式は null を返します。
インデックスが null、負の値、または範囲外の場合、set 式は実行時にエラーを報告します。
プロパティ size は、リストのサイズを返します。
var size := cities.size;
リストを反復処理できます。詳細については、for ループ を参照してください。
複数値スキーマフィールド
複数値のスキーマフィールドは、リスト型と見なされます。
複数値スキーマフィールドは、値の最大数 (maxOccurs) が 1 より大きいか、「unbounded」に設定されているフィールドです。
インデックス付き表記は、値にアクセスまたは設定するために使用されます。最初のインデックスは 0 です。次の例では、レコードフィールド「OfficeAddress/street」は複数値です。
// Return the second line of the street part of the address.
return OfficeAddress.street[1].
typeof キーワードは、多値フィールドで使用できます (typeof キーワードの章を参照)。
typeof キーワード
フィールドまたは変数に応じて型を指定するには、キーワード typeof を使用します。
たとえば、レコードフィールド OfficeAddress の型を参照するには、次の構文を使用します。
typeof record.OfficeAddress
フィールドが複数値の場合、リストと見なされます。次の構文を使用して、リストの項目の型を参照できます。
typeof record.Addresses[*]
データモデルで宣言された型
パス /root/User/Address を持つ current データモデル内のフィールドの型を参照するには、次の構文を使用します。
var address: .User.Address;
「/」が「.」に置き換えられ、最初のステップが省略されていることに注意してください。
エイリアス 'hist' で宣言されたデータモデル内のパス /root/Sales/Amount を持つデータモデルからフィールドの型を取得するには、次の構文を使用します。
var amount: hist.Sales.Amount
フィールドが複数値の場合、リストと見なされます。次の構文を使用して、リストの項目の型を参照できます。
var products: hist.Sales.products[*]
レコード、テーブル、主キー
データモデル sample のパス "/root/test/table" がモデル用である場合、レコードを指定するには次のいずれかの構文を使用します。
var immutableRecord1: sample.test.table;
var immutableRecord2: immutable sample.test.table
var mutableRecord: mutable sample.test.table
修飾子が指定されていない場合、型は不変です。
テーブルを指定するには、次の構文を使用します。
var aTable: tableof sample.test.table;
aTable := db.findTable<.directory.Customer>(_ebx.dataset);
主キーを指定するには、次のいずれかの構文を使用します。
var immutablePrimaryKey1: primarykeyof sample.test.table;
var immutablePrimaryKey: immutable primarykeyof sample.test.table
var mutablePrimaryKey: mutable primarykeyof sample.test.table
修飾子が指定されていない場合、主キーは不変です。
型修飾子
型は次のようになります。
-
immutable: この型の項目を変更することはできません。
-
mutable: この型の項目は、変更できる可能性があります。
単純型は常に不変です。
互換性のある不変型の変数または戻り値に変更可能な値を割り当てることはできますが、変更可能な変数または戻り値に変更不可能な値を割り当てると、コンパイル時にエラーが発生します。
次のいずれかの構文を使用して不変型を指定できます。
immutable typeof record.OfficeAddress
immutable .User.Address
immutable hist.Sales.Amount
次のいずれかの構文を使用して、変更可能な型を指定できます。
mutable typeof record.OfficeAddress
mutable .User.Address
mutable hist.Sales.Amount
一部の型では immutable または mutable キーワードがサポートされておらず、コンパイル時にエラーが発生する場合があります。
リストは次のようになります。
-
unmodifiable: 挿入時に項目を削除することはできません。項目は不変の場合もそうでない場合もあります。
-
modifiable: 項目を挿入時に削除できます。項目は不変の場合もそうでない場合もあります。
変更可能なリストを、互換性のある変更不可能なリスト型の変数または戻り値に割り当てることはできますが、変更不可能なリストを変更可能な変数または戻りリストに割り当てると、コンパイル時にエラーが発生します。
可変複合型またはリストオブジェクトを変更できますが、オブジェクトの一部の属性の変更を妨げる可能性のある他の制約が適用される場合があります。
次の構文を使用して、変更不可能なリストタイプを指定できます。
unmodifiable typeof _ebx.record.Addresses[*]
unmodifiable .User.children[*]
unmodifiable hist.Sales.products[*]
次の構文を使用して、変更可能なリストタイプを指定できます。
modifiable typeof _ebx.record.Addresses[*]
modifiable .User.children[*]
modifiable hist.Sales.products[*]
キーワード raise
トリガーまたは関数フィールドの実行中にエラーを報告するには、キーワード raise を使用します。
メッセージなしでエラーを発生させるには、次の構文を使用します。
raise code;
メッセージとともにエラーを発生させるには、次の構文を使用します。
raise code, message;
-
code はエラー識別子です。32 の整数値にする必要があります。
-
message は表示されるエラーメッセージを指定します。これはオプションの文字列値です。
関数フィールドでキーワード raise を使用する例
// this function raises an error when the name is empty.
uses core.string as string;
export function getValue(): string
begin
var name := _ebx.record.name;
if not string.isEmpty(name) then
return name;
//value cannot be empty!
raise 341i;
end
テーブルトリガーでキーワード raise を使用する例
// this trigger checks sales amount and reports an error if the allowed amount is exceeded.
export procedure onBeforeCreate()
begin
if (_ebx.record.amount > 1000) then
raise 450 , 'Sales Amount '| _ebx.record.amount |' has exceeded the allowed amount of 1000';
end
リテラル
文字列リテラル
文字列リテラルは、一重引用符で囲まれた Unicode 文字の任意のシーケンスにすることができます。次の表は、エスケープシーケンスで置き換える必要のある文字を示しています。
| 文字 | エスケープシーケンス |
|---|---|
| タブ | \t |
| バックスペース | \b |
| 改行 | \n |
| キャリッジリターン | \r |
| フォームフィード | \f |
| 一重引用符 | \' |
| バックスラッシュ | \\ |
\uXXXX 形式の Unicode エスケープシーケンスを使用して文字を指定します。XXXX は Unicode 文字の 16 進数コードです。
例
| 値 | 構文 |
|---|---|
| O’Harra | 'O\'Harra' |
| Noël | 'No\u00EBl' |
| été | '\u00e9t\u00E9' |
注意
無効なエスケープまたは Unicode シーケンスは、コンパイル時にエラーを生成します。
10 進リテラル
次の 10 進形式がサポートされています。
| 形式 | 例 |
|---|---|
| 小数部なし | 546 -67 |
| 浮動小数点数 | 54.987 -433.876 0.00054 -0.0032 |
| 指数表記 | 34.654e-5 -45E+65 1.543e23 |
整数 (32ビット) リテラル
整数 32 ビットリテラルの形式は、 90324i または -543i のようになります。
値は -2147483648i から 2147483647i までの範囲でなければなりません。
注意:i 文字がない場合、値は小数と見なされます。
タイムスタンプリテラル
タイムスタンプリテラルの形式は dt(yyyy-MM-dd hh:mm:ss.sss) です。
秒はオプションです。指定されていない場合は 0 と見なされます。秒は、ミリ秒の精度までの小数部を持つことができます。
グレゴリオ暦で無効な日付は、コンパイル時にエラーを生成します。
例
dt(2010-01-02 00:00:00.000)
dt(2019-2-3 12:56:7)
dt(2019-2-3 12:56:7.5)
dt(2019-5-7 1:6)
日付リテラル
日付リテラルの形式は d(yyyy-MM-dd) です。
グレゴリオ暦で無効な日付は、コンパイル時にエラーを生成します。
例
d(2010-01-02)
d(2019-2-3)
dt(2019-5-7)
時間リテラル
時間リテラルの形式は t(hh:mm:ss.sss) です。
秒はオプションです。指定されていない場合は 0 と見なされます。秒は、ミリ秒の精度までの小数部を持つことができます。
無効な時間は、コンパイル時にエラーを生成します。
例
t(00:00:00)
t(12:56:7)
t(12:56:7.5)
t(1:6)
ブール値リテラル
ブール値リテラルは、キーワード true またはキーワード false のいずれかです。
Null リテラル
null リテラルはキーワード null です。
このリテラルは、次の状況でのみ使用してください。
-
変数またはフィールドを設定する
-
戻り値
注意
このキーワードを使用して、変数またはフィールドが null かどうかをテストすることはできません。代わりに、関数 isNull() を使用してください。
演算子
優先度
デフォルトでは、操作の評価順序は優先度と結合性に基づいています。括弧を使用して、評価の順序を明示的に示します。
次の表は、優先度の高いものから低いものへのすべての演算子と、それらの関連性を示しています。
| 優先度 | 演算子 | オペランド型 | 結果型 | 結合性 |
|---|---|---|---|---|
| 9 | (リストのエレメントへのアクセス) . (フィールドへのアクセス) () (括弧) | リストインデックスは int または 10 進数でなければなりません。 | 任意の型にすることができます。 | 左から右へ |
| 8 | not | boolean | boolean | |
| 7 | * / | 小数または整数 | decimal | 左から右へ |
| 6 | + - | decimal または int | decimal | 左から右へ |
| 5 | (文字列の連結) | string | string | |
| 4 | < <= > >= | 文字列、小数点、整数、タイムスタンプ、日付、時刻 (3)。 | boolean | 連想的ではありません。 |
| 3 | = <> | string、decimal、int、timestamp、date、time、boolean (3) | boolean | |
| 2 | and | boolean | boolean | 左から右へ |
| 1 | or | boolean | boolean | 左から右へ |
算術演算子
すべての算術演算子 ( * 、/ 、+ 、 - ) は、34 桁の精度 (IEEE 754R Decimal128 形式) の decimal で評価されます。ìnt 型の値は、比較の前に常に decimal に変換されます。
いずれかのオペランドが null の場合、結果は null になります。
int 型変数に割り当てられると、decimal 値は自動的に変換されます。値が整数ではない、2147483647 より大きい、または -2147483648 より小さいために値を変換できない場合、エラーが発生します。
文字列連結演算子
文字列連結演算子 ( | ) オペランドは任意の型にすることができ、連結前に自動的に文字列に変換されます。null 値は空の文字列に置き換えられます。
文字列連結演算子 ( | ) は、連結を実行する前に、すべての null オペランドを空の文字列に置き換えます。
ブール演算子
ブール演算子は、三値論理 (ternary logic) とも呼ばれる 三値論理 を使用します。この論理は SQL でも使用されます。
ブール変数は、true、false、null の 3 つの真値のいずれかを持つことができます。
二値論理と同様に、三値論理には and、or、not などの演算子があります。ただし、これらの演算子の動作は、null 値を次のように処理するように拡張されています。
-
not: true を false に、false を true に反転しますが、null は変更しません。
-
and: すべてのオペランドが true の場合、結果は true です。いずれかのオペランドが false の場合、結果は false です。少なくとも 1 つのオペランドが null で、かつ false のオペランドがない場合、結果は null です。これは、1 つ以上の false オペランドがすべての null オペランドを上書きすることを意味します。
-
or: いずれかのオペランドが true の場合、結果は true です。すべてのオペランドが false の場合、結果は false です。少なくとも 1 つのオペランドが null で、かつ true のオペランドがない場合、結果は null です。これは、1 つ以上の true オペランドがすべての null オペランドを上書きすることを意味します。
比較演算子
比較演算子 ( < 、<= 、> 、=> 、= および <> ) は、同じ型の 2 つのオペランドを比較します。 int 型の値は、比較の前に常に decimal に変換されます。
コンパレータの戻り値は boolean 型です。この値は true または false のみで、すべてのオペランドが null でない場合に限ります。オペランドのいずれかが null の場合、それは null です。
ビルトインおよびユニット関数
ビルトイン関数とユニット関数は通常、パラメーターが null の場合、 null を返します。
例外もあるため、必ず API ドキュメント を参照してください。
割り当て
次の表に、すべての割り当て演算子を示します。
| 演算子 | オペランド型 | 説明 |
|---|---|---|
| := | あらゆる型に使用できます。 | 標準割り当て。 |
| = | string | |
| += | decimal、int | a += b は a:= a + bと同等 |
| -= | decimal、int | a-= b は a := a-b と同等 |
| *= | decimal、int | a *= b は a := a * b と同等 |
| /= | decimal、int | a /= b は a := a / b と同等 |
ステートメントブロック
ステートメント ブロックは、複数のステートメントをグループ化するために使用されます。キーワード begin で始まり、キーワード end で終わります。ほとんどのステートメントは ; で終了する必要があります。
begin
statement_1;
statement_2;
end
ステートメントブロックには、ステートメントブロックを含めることもできる 1 つ以上のステートメントブロックを含めることができます。
begin
statement_1;
begin
statement_2_1;
statement_2_3;
begin
statement_3_1;
statement_3_2;
end
end
statement_3;
end
変数と定数
はじめに
ブロック内の任意のステートメントは、変数または定数を宣言できます。
変数または定数の型は常に、変数が宣言されたときに固定されます。
代入演算子 := を使用して、値を変数に割り当てることができます。
間違った型の値を変数に割り当てたり、宣言後に定数の値を変更したりすると、エラーになります。
割り当てステートメント
型検出を使用した宣言
変数または定数型は、宣言時に初期化すると自動的に検出できます。この機能は型推論と呼ばれます。
変数の構文は次のとおりです。
var variable_name := a_value;
定数の構文は次のとおりです。
const const_name := a_value;
例
begin
var firstName := 'John'; // Variable of type string.
var age := 30i; // Variable of type int.
var cost := 34.54; // Variable of type decimal.
var value := 43; // Variable of type decimal not int
// because the letter `i` is missing.
var address := record.address; // Variable of an immutable complex.
const MAX_AGE := 100i; // Constant of type int.
const DEFAULT_COUNTRY := 'France'; // Constant of type string.
end
注意
定数は必ずしも不変ではありません。
明示的な型の定義
変数の型を明示的に指定することができます。
変数の構文は次のとおりです。
// Following variable initial value is null.
var variable_1_name : variable_1_type;
// Value a_value must be compatible with type variable_1_type.
var variable_2_name : variable_1_type := a_value;
定数の構文は次のとおりです。
const const_name : variable_1_type := a_value;
例
begin
var firstName : string;
firstName := 'John';
var age : int;
age := 30;
var address : typeof record.address;
address := record.address;
const MAX_AGE : int := 100;
const DEFAULT_COUNTRY : string := 'France';
end
初期化されていない変数の値は null です。
begin
var firstName : string;
if isNull(fistName) then
doSomething(); // Statement will be executed.
end
次のステートメントにはエラーがあります。
begin
// Following will not compile because variable is not initialized and no type
// is defined.
var firstName;
// Following will not compile because variable type is decimal and value is
// a string.
var amount : decimal := 'test';
end
参照変数 (ref)
参照変数は、コンポーネント型の値への可変参照を格納します。これらはボックス化された値のように動作します。
-
読み取りは参照値に自動的に逆参照されます。
-
代入は参照値に書き込みます。
構文
ref 宣言は、形状において var を反映しています。初期化子が提供されている場合、型はオプションです。
// With explicit type and initializer
ref counter: int := 0i;
// With explicit type only (initialized to null)
ref name: string;
// With initializer only (type inferred from initializer)
ref price := 12.50;
型が指定されていない場合、null 以外の型の初期化子が必要です。そうでない場合、コンパイル時エラーが報告されます (var と同じルール)。
使用法
ref 変数への読み取りと書き込みは、参照値を直接ターゲットとします。.value フィールドにアクセスする必要はありません。
begin
ref total: decimal := 0.0;
total += 10; // increments the referenced value
var x := total; // reads the referenced value
ref title := 'Mr'; // type inferred as string
title := title | 's';
end
リストとインデックスで ref を使用することもできます。代入は通常のリスト要素の格納のように動作します。
uses core.list as list;
begin
ref numbers: modifiable list<int> := list.of<int>();
list.add(numbers, 1i);
list.add(numbers, 2i);
end
注意: ref という単語は、グローバルに予約されたキーワードではありません (下位互換性のため)。ref を引用符なしで識別子として使用できます。宣言コンテキストで、ref がステートメントの先頭に現れる場合、それは参照変数宣言として解析されます。その位置で文字通り ref という名前の変数が必要な場合は、引用符付き識別子 (例: "ref") を使用してください。
トランザクションでの ref の使用
ref は、execute transaction ブロック内で計算された値をキャプチャし、後でそれを返すのに特に役立ちます。
uses core.data as db;
export function updateCounter(): int
begin
ref result: int; // will be assigned inside the transaction block
execute transaction tr on db.findDataspace('sample')
begin
// Compute under transaction context (read/update data as needed)
result := 42i;
end
// `result` carries the value out of the transaction block
return result;
end
スコープ
変数または定数範囲は、その宣言から、宣言されたステートメントブロックの終わりまでに及びます。
begin
var firstName := 'John';
var lastName := 'Doe';
begin
// Following is OK because firstName and lastName are visible.
var fullName := firstName | ' ' | lastName;
....
end
// Following will NOT compile because fullName is out of the scope.
var message := 'Please contact ' | fullName;
end
同じ名前の変数を同じブロックまたはサブブロックに存在させることはできません。
begin
var firstName := 'John';
begin
var firstName := 'Bob'; // Error! Variable already declared.
....
end
end
以下は正しい記述です。
begin
begin
var firstName := 'Bob';
....
end
// The following is not an error, because block where previous variable was
// declared is ended.
var firstName := 'John';
end
複合型変数
複合型の変数または定数は、型検出または typeof キーワード を使用して宣言できます。
ドット表記は、複合型の変数のフィールドにアクセスするために使用されます。
例
// Declaration using type detection.
var address1 := _ebx.record.OfficeAddress;
// Declaration using typeof notation.
var address2 : typeof _ebx.record.OfficeAddress;
address2 := address1;
各ステップ (ドットで区切られた部分) は 識別子 です。これは、次の引用表記をどのステップにも使用できることを意味します。
var city := _ebx.record."OfficeAddress".City;
これは、予約済みのキーワードに相当するステップや、マイナス文字 ( - ) やドット ( . )などの引用符で囲まれていない識別子と互換性のない文字を使用するステップに役立ちます。
実行時に、どのステップも null と評価される可能性があります。この場合、完全なフィールド式は null と評価されます。
複数値フィールド
定義済み変数
はじめに
データスペース
定義済み変数 \_ebx.dataspace は、現在のデータスペースに関する情報へのアクセスを提供します。
この変数には次のフィールドがあります。
| 名前 | タイプ | 説明 |
|---|---|---|
| name | string | データスペースの名前。データスペースの名前空間とスナップショットの名前空間は独立しているため、返される文字列は名前空間の 1 つのコンテキストにおける識別子にすぎません。グローバル データスペースまたはスナップショット識別子には、フィールド id を使用します。 |
| identifier | string | データスペースまたはスナップショットの永続的な識別子。name と比較すると、この識別子は、この ID がデータスペース用かスナップショット用かをさらに指定します。 |
| isSnapshot | boolean | データスペースがスナップショットの場合は true であり、データスペースがブランチの場合は false です。 |
例
// Returns details on the current dataspace.
export function getValue(): string
begin
if _ebx.dataspace.isSnapshot then
return 'Snapshot: ' | dataspace.name;
else
return 'Branch: ' | dataspace.name;
end
データセット
定義済み変数 \_ebx.dataset は、現在のデータセットに関する情報へのアクセスを提供します。
この変数には次のフィールドがあります。
| 名前 | タイプ | 説明 |
|---|---|---|
| name | string | データセットの名前 |
| dataspace | dataspace | データセットのデータスペース |
例
// Returns the current dataset name.
export function getValue(): string
begin
return _ebx.dataset.name;
end
注意: \_ebx.dataset 定義済み変数は、トリガーが afterDelete タイプの場合、データセットトリガーのコンテキストでは使用できません。
ルート
定義済み変数 \_ebx.root は、現在のスクリプトがテーブルトリガー、データセットトリガー、または関数フィールド用の場合に使用できます。この変数は、現在のデータセットのフィールドへの読み取り専用アクセスを提供します。
そのフィールドは、現在の EBX® スキーマによって定義されています。
例
// this function field returns information on current dataset data.
export function getValue(): string
begin
return _ebx.root.City | ' ' | _ebx.root.Region;
end// this table trigger logs information of current dataset data.
uses core.log as log;
export procedure onNewContext()
begin
log.info(_ebx.root.City | ' ' | _ebx.root.Region);
end// this dataset trigger logs information of current dataset data.
uses core.log as log;
export procedure onAfterDuplicate()
begin
log.info(_ebx.root.Country);
end
関数とプロシージャ
関数
関数は、値を返すメソッドです。
パラメーターのない関数の構文は次のとおりです。
function function_name(): return_value_type
begin
....
return a_value;
end
パラメーターを使用する関数の構文は次のとおりです。
function function_name(
parameter_1 : parameter_1_type,
parameter_2 : parameter_2_type...,): return_value_type
begin
....
return a_value;
end
const キーワードを使用してパラメーター定数を宣言することができます。
function function_name(const parameter_1 : parameter_1_type): return_value_type
begin
....
return a_value;
end
関数の最後のステートメントは常に return ステートメントにする必要があります。この関数には、必要な数の return ステートメントを含めることができます。
例
function getFullName(firstName: string, lastName: string): string
begin
if isNull(firstName) then
return lastName;
return firstName | ' ' | lastName;
end
宣言された値とは異なる値を返すことは違法です。
function getValue(): string
begin
return 0; // Error! Return type is decimal, not string.
end
プロシージャ
プロシージャは、値を返さないメソッドです。
パラメーターのないプロシージャの構文は次のとおりです。
procedure procedure_name()
begin
....
end
パラメーターを使用するプロシージャの構文は次のとおりです。
procedure procedure_name(
parameter_1 : parameter_1_type,
parameter_2 : parameter_2_type...)
begin
....
end
const キーワードを使用してパラメーター定数を宣言することができます。
function procedure_name(const parameter_1 : parameter_1_type): return_value_type
begin
....
return a_value;
end
プロシージャに return ステートメントを含めることはできませんが、関数には必要な数の return ステートメントを含めることができます。プロシージャステートメントは値を返すことができません。
エクスポート済み関数またはプロシージャ
パラメーター
単純型パラメーターは値によって渡されます。これは、関数またはプロシージャが元の値のコピーを受け取ることを意味します。
複合型とリスト型は参照によって渡されます。これは、関数またはプロシージャが元のオブジェクトを受け取ることを意味します。関数またはプロシージャがオブジェクトを変更すると、元のオブジェクトが変更されます。
If ステートメント
「If then」ステートメント
「if then」ステートメントの構文は次のとおりです。
if condition-expression then
then-statement
条件式はブール型として評価される必要があります。
then ステートメントは ステートメントブロックにすることができます。これは、条件式が true の場合にのみ実行されます。
「If then else」ステートメント
「if then else」ステートメントの構文は次のとおりです。
if condition-expression then
then-statement
else
else-statement
条件式はブール型にする必要があります。
「then」または「else」ステートメントは、ステートメントブロックにすることができます。then ステートメントは、条件式が true の場合にのみ実行されます。else ステートメントは、条件式が false または null の場合にのみ実行されます。
If ステートメントと三値論理
次のコード:
if condition-expression then
statements-a;
else
statements-b;
次のコードとは同等ではありません。
if not condition-expression then
statements-b;
else
statements-a;
実際、式が null の場合、どちらの場合も else ステートメントが実行されます。
次の例では、a または b のいずれかが null の場合、reportError() ステートメントは実行されません。
if a <> b then
begin
reportError();
return;
end
doSomething();
return;
これは意図した動作ではない可能性があります。代わりに、次のコードを使用できます。
if a = b then
doSomething();
else
reportError();
return;
または
if isTrueOrNull(a <> b) then
begin
reportError();
return;
end
doSomething();
return;
上記のコード例では、null 値を持つことは常にエラーであると見なしています。a と b の両方が null であることがエラーではない場合、次のようなコードを使用できます。
if (isNull(a) and isNull(b)) or (a = b) then
doSomething();
else
reportError();
ループ
「For in do」ループ
「for in do」ループステートメントは、リストの各項目を選択し、ブロックステートメントを実行するために使用されます。構文は次のとおりです。
for item_variable_name in list do
begin
statement_a;
statement_b;
...
end
ブロックステートメントは、リストの値ごとに 1 回実行されます。各反復で、読み取り専用アイテム変数は、リストの順序でリストの値を取ります。
item 変数の名前は、現在の範囲内で一意にする必要があります。一意でない場合、コンパイル時にエラーが生成されます。
項目ごとに 1 つのステートメントを実行する必要がある場合は、次のより単純な構文を使用できます。
for item_variable_name in list do statement;
次の例は、複合体のリストを繰り返します。
// Concatenate all city addresses in a single string.
var cities := '';
for address in _ebx.record.Addresses do
begin
if cities <> '' then cities |= ', ';
cities |= address.city;
end
「While do」ループ
「while do」ループステートメントは、条件が true になるまでステートメントブロックを実行するために使用されます。次の構文があります。
while condition do
begin
statement_a;
statement_b;
...
end
単一のステートメントを実行する必要がある場合は、より単純な、次の構文を使用できます。
while condition do statement_a;
次の例では、値の階乗を計算します。
function factorial(value : decimal): decimal
begin
var factorial := value;
while(value > 1) do
begin
value -= 1;
factorial *= value;
end
return factorial;
end
範囲外のエラーを回避するために、int 型の代わりに decimal 型が使用されます。
ユニット
EBX® は、「ユニット」にパッケージ化された API を提供します。
ユニットは、複数の機能またはプロシージャを定義できます。
デフォルトのものを除いて、「Unit」は使用前に宣言する必要があります。宣言はスクリプトの先頭にあり、次の型の構文に従う必要があります。
uses package_name.unit_name_a;
uses package_name.unit_name_b as alias_b;
現在、package\_name は常に core です。ユニットエイリアスは、スクリプト内で一意にする必要があります。
メソッドは、次の構文を使用して参照できます。
value1 := package_name.unit_name_a.function_a();
value2 := package_name.unit_name_a.function_b(parameter1, parameter2);
value3 := alias_a.function_c();
value4 := alias_a.function_d(parameter1, parameter2);
package_name.unit_name_a.procedure_a();
package_name.unit_name_a.procedure_b(parameter1, parameter2);
alias_a.procedure_c();
alias_a.procedure_d(parameter1, parameter2);
次の例では、core.list ユニットを使用してリストを作成します。
uses core.list as list;
export function getValue(): typeof _ebx.record.Cities
begin
return list.of('Paris', 'Bruxelles', 'Berlin');
end
提供されているユニットの詳細については、API ドキュメント を参照してください。
SQL クエリ
EBX® スクリプトは SQL クエリ (select 式) を実行できます。
SQL クエリには、埋め込み と 動的 の 2 種類があります。
埋め込みクエリ
可能な限り埋め込みクエリを使用してください。これらはコンパイル時に検証されるため、実行時ではなくコンパイル時にエラーを検出できます。
埋め込みクエリはバッククォートで囲み、sql をプレフィックスとして付ける必要があります。
サンプル:
uses core.data as d;
// References to data models used by the queries are declared at the beginning of the script.
references model myModel from module "ebx-test" as m;
// Syntax of the query is validated at compile time.
var query := sql `select u.f_name as firstName, u.l_name as lastName from m.users u where location = ?`;
// Adds the dataset corresponding to the model 'm' to the query.
d.addDataset(query, ‘m', d.findDataset(d.findDataspace('myDataspace'), 'myDataset'));
// Sets the parameter value for the query. Parameter existence and type are checked at compile time.
// The parameter name is parameter_<position>.
query.parameter_O := 'France';
// Executes the query and fetches rows.
for tuple in d.execute(query) do
begin
// Retrieves the values of the row. Existence and type are checked at compile time.
// The name of a value is the alias set in the query or the column name of no alias are set.
var firstName := tuple.firstName;
var lastName := tuple.lastName;
end;
d.close(query); // Optional. Query is closed automatically if the last tuple is reached or when script execution ends.
動的クエリ
動的クエリは実行時に構築されるため、コンパイル時に検証することはできません。不正なクエリは実行時にエラーを生成します。
サンプル:
uses core.data as d;
// References to data models used by the queries are declared at the beginning of the script.
references model myModel from module "ebx-test" as m;
// Builds the query expression.
var queryExpression := 'select u.f_name as firstName, u.l_name as lastName from m.users u';
queryExpression += ' where location = ?';
// Creates the query.
var query := d.createQuery(queryExpression);
// Adds the dataset corresponding to the model 'm' to the query.
db.addDataset(query, ‘m', d.findDataset(d.findDataspace('myDataspace'), 'myDataset'));
// Sets the parameter value for the query. Parameter existence and type are checked at runtime.
d.setParameter(query, 0, 'France');
// Executes the query and fetches rows.
for tuple in d.execute(query) do
begin
// Retrieves the values of the row. Existence and type are checked at runtime.
// The name of a value is the alias set in the query or the column name of no alias are set.
var firstName := d.field<string>(tuple, 'firstName');
var lastName := d.field<string>(tuple, 'lastName');
end;
d.close(query); // Optional. Query is closed automatically if the last tuple is reached or when script execution ends.
クエリセッション
スクリプトが SQL クエリにセッションを明示的に設定できるように、プロパティ query.session が提供されています。SQL クエリのアクセス制御を無効にするには、クエリセッションに null 値を設定できます。
// create a sql query
var query := sql `Select b.col from tableB b`;
// set a session to sql query
query.session:= ...;
// get userId and locale of the query session
var userId:=query.session.userId;
var locale:=query.session.locale;
注意: トリガーおよびスクリプトタスクのコンテキストでは、現在のユーザーセッションはデフォルトで SQL クエリに設定されます。関数値のコンテキストでは、SQL クエリにデフォルトのユーザーセッションは設定されません。
ログ取得とデバッグ
ユニット unit.log は、メッセージをログに記録するために使用できる関数を提供します。
もう 1 つの便利な機能は、スクリプトの実行中にランタイムでエラーが発生した場合、通常、エラーが発生したスクリプトの行とともにログに記録されることです。
初期スクリプト
DMA を使用して新しい機能フィールドまたはテーブルトリガーが作成されると、初期スクリプトが作成されます。
次の例は、テーブルトリガー用に作成されたスクリプトです。
uses core.datetime as datetime;
export procedure onBeforeCreate()
begin
record.inscriptionDate := datetime.now();
end
次の例は、文字列型の関数フィールド用に作成されたスクリプトです。
// Returns the full name.
export function getValue(): string
begin
return _ebx.record.FirstName | ' ' | _ebx.record.LastName;
end