関数 DSL (ドメイン固有言語) を使用して、関数フィールドを定義します。
この DSL は、手続き型で静的に型付けされた言語です。
関数フィールドを作成および変更するには、Data Model Assistant (DMA) を使用します。
データモデルアシスタント (DMA) には、コンテキストコードの補完を提供するスクリプトエディターが含まれています。
スクリプトの構造は次のとおりです。
<unit usage statement 1> <unit usage statement 2> ... <unit usage statement N> <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 := record.FirstName | ' ' | record.LastName; for street in record.OfficeAddress.Street do begin address |= '\n' | street; end; address |= '\n' | record.OfficeAddress.ZipCode | ' ' | record.OfficeAddress.City; address |= '\n' | record.OfficeAddress.Country; return address; end |
Unicode 文字セットがサポートされています。
DSL では大文字と小文字が区別されます。
1 行のコメントは、//から現在の行の終わりまで拡張されます。
// This is a comment if record.LastName = 'Doe' then // This is another comment. return true; |
複数行のコメントは /* から始まり、 */ で終わります。
/* This is an example of a multi-line comment */ if record.isActive then return false; |
予約済みのキーワードは、 and、or、not、uses、as、export、typeof、mutable、immutable、unmodifiable、function、procedure、const、var、if、then、else、for、while、in、 do、begin、end、return、true、false、null です。
予約済みのキーワードは、プレーンな (引用符で囲まれていない) 識別子として使用することはできません。
引用符なしの識別子 は、文字、数字、またはアンダースコア (_) の無制限の長さのシーケンスです。最初の文字は、文字またはアンダースコアにする必要があります。
有効な文字は a から z および A から Z です。有効な数字は 0 から 9 です。
引用符なしの識別子は、予約済みのキーワードと等しくない場合があります。
引用符付き識別子は、二重引用符 (")を除く任意の Unicode 文字の無制限の長さです。
引用符で囲まれた識別子は、二重引用符で囲んで使用する必要があります。
引用符なしの識別子は、二重引用符で囲んで使用できます。これは、識別子「a_name」が a_name と等しいことを意味します。
引用符付きの識別子は予約済みのキーワードにすることができます。
次の単純な型がサポートされています。
タイプ | キーワード | プロパティ | EBX® 対応型 |
---|---|---|---|
ブール値 | boolean | xs:boolean | |
10 進数 (無制限の精度) | decimal | xs:decimal | |
整数 (32ビット) | int | xs:int xs:integer | |
文字列 | string | xs:string xs:Name osd:text osd:html osd:email osd:password 1 osd:color osd:dataspaceKey osd:datasetName | |
タイムスタンプ (ミリ秒の精度でタイムゾーンなし) | timestamp | 年 月 (1 から 12) 日 (1 から 31) 時間 (0 から 23) 分 (0 から 59) 秒 (0.000 から 59.999) | xs:dateTime |
日付 (タイムゾーンなし) | date | 年 月 (1 から 12) 日 (1 から 31) | xs:date |
時間 (ミリ秒の精度) | time | 時間 (0 から 23) 分 (0 から 59) 秒 (0.000 から 59.999) | xs:time |
ロケール | locale | osd:locale | |
URI (Uniform Resource Identifier) | uri | xs:anyURI | |
リソース | resource | osd:resource |
1 タイプ osd:password の関数フィールドを定義することはできません。
複合型は、EBX® スキーマで定義されたグループ (複合) ノードの型です。
詳細については、複合型の変数の章を参照してください。
スキーマノードの型への参照 (たとえば、関数パラメーターまたは変数を宣言するとき) は、 keyword typeof の使用を意味します。
DSL はリストをサポートしています。次の構文を使用してリストを宣言します。
list<item_type> |
次の構文を使用して、変更不可能なリストを宣言します。
unmodifiable list<item_type> |
リストが変更できない場合、項目を追加、削除、または置き換えることはできません。リストの項目は、その型に応じて、変更できる場合とできない場合があります。
インデックス付き表記を使用して、値を設定または取得します (最初のインデックスは 0)。
// Set first value of cities. cities[0] := 'Paris'; // Get the second item of cities. return cities[1]; |
インデックスは、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 キーワードは、多値フィールドで使用できます (keyword typeof の章を参照)。
不変の複合型またはリストオブジェクトを変更することはできません。
可変複合型またはリストオブジェクトを変更できますが、オブジェクトの一部の属性の変更を妨げる可能性のある他の制約が適用される場合があります。
単純型は常に不変です。
変数または互換性のある不変型の戻り値に可変値を割り当てることができますが、不変値を可変変数または戻り値に割り当てると、コンパイル時にエラーが発生します。
フィールドまたは変数に応じて型を指定するには、キーワード typeof を使用します。このキーワードは、キーワード mutable または immutable の後に使用できます。
たとえば、レコードフィールド OfficeAddress の型を参照するには、次の構文を使用します。
typeof record.OfficeAddress |
デフォルトでは、レコードフィールドの型は常に不変です。次の構文を使用して、可変型を指定できます。
mutable typeof record.OfficeAddress |
フィールドが複数値の場合、リストと見なされます。次の構文を使用して、リストの項目の型を参照できます。
typeof record.Addresses[*] |
可変形式の型では、キーワード「mutable」を使用できます。
mutable typeof record.Addresses[*] |
型に変更可能な形式がない場合、キーワードは単に無視されます。これは単純な型の場合です。
===
文字列リテラルは、一重引用符で囲まれた Unicode 文字の任意のシーケンスにすることができます。次の表は、エスケープシーケンスで置き換える必要のある文字を示しています。
文字 | エスケープシーケンス |
---|---|
タブ | \t |
バックスペース | \b |
改行 | \n |
キャリッジリターン | \r |
フォームフィード | \f |
一重引用符 | \' |
バックラッシュ | \\ |
\uXXXX 形式の Unicode エスケープシーケンスを使用して文字を指定します。XXXX は Unicode 文字の 16 進数コードです。
例
値 | 構文 |
---|---|
O’Harra | 'O\'Harra' |
Noël | 'No\u00EBl' |
été | '\u00e9\u00E9' |
注意
無効なエスケープまたは Unicode シーケンスは、コンパイル時にエラーを生成します。
次の 10 進形式がサポートされています。
形式 | 例 |
---|---|
整数 | 546 -67 |
浮動小数点数 | 54.987 -433.876 0.00054 -0.0032 |
指数表記 | 34.654e-5 -45E+65 1.543e23 |
タイムスタンプ リテラルの形式は 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 かどうかをテストすることはできません。代わりに、関数 isNull() を使用してください。
デフォルトでは、操作の評価順序は優先順位と結合性に基づいています。括弧を使用して、評価の順序を明示的に示します。
次の表は、優先順位の高いものから低いものへのすべての演算子と、それらの関連性を示しています。
優先順位 | 演算子 | オペランド型 | 結果型 | 結合性 |
---|---|---|---|---|
9 | [] (リストのエレメントへのアクセス) . (フィールドへのアクセス) () (括弧) | リストインデックスは 10 進数にする必要があります。 | 任意の型にすることができます。 | 左から右へ |
8 | not | ブール値 | ブール値 | |
7 | * / | 10 進数 | 10 進数 | 左から右へ |
6 | + - | 10 進数 | 10 進数 | 左から右へ |
5 | | (文字列の連結) | 文字列 | 文字列 | 左から右へ |
4 | < <= >> >= | 文字列、10 進数、タイムスタンプ、日付、時刻 (3)。 | ブール値 | 連想的ではありません。 |
3 | = <> | 文字列、10 進数、タイムスタンプ、日付、時刻、ブール値 (3)。 | ブール値 | |
2 | and | ブール値 | ブール値 | 左から右へ |
1 | または | ブール値 | ブール値 | 左から右へ |
すべての算術演算子 ( * 、/ 、+ および - ) は、34 桁の精度 (IEEE 754R Decimal128 形式)。いずれかのオペランドが null の場合、結果は null になります。
int 型変数に割り当てられると、10 進値は自動的に変換されます。値が整数ではない、2147483647 より大きい、または-2147483648 より小さいために値を変換できない場合、エラーが発生します。
文字列連結演算子 ( | ) オペランドは任意の型にすることができ、連結前に自動的に文字列に変換されます。null 値は空の文字列に置き換えられます。
文字列連結演算子 ( | ) は、連結を実行する前に、すべての null オペランドを空の文字列に置き換えます。
ブール演算子はスレッド値ロジックを使用します。
AND 演算子の真偽 (true/false) 表は次のとおりです。
And | true | false | null |
true | true | false | null |
false | false | false | false |
null | null | false | null |
OR 演算子の真偽 (true/false) 表は次のとおりです。
Or | true | false | null |
true | true | true | true |
false | true | false | null |
null | true | null | null |
比較演算子 ( < ,<= ,> ,=> ,= and <> ) は、同じ型の 2 つのオペランドを比較します。int 型の変数は、比較前に常に 10 進数に変換されます。
コンパレータの戻り値は boolean 型です。すべてのオペランドが null でない場合のみ、この値は true または false になります。オペランドのいずれかが null の場合、それは null です。
ビルトイン関数とユニット関数は通常、パラメーターが null の場合、 null を返します。
例外もあるため、必ず API ドキュメント を参照してください。
次の表に、すべての割り当て演算子を示します。
演算子 | オペランド型 | 説明 |
---|---|---|
:= | あらゆる型に使用できます。 | 標準割り当て。 |
|= | 文字列 | a |= b は a:= a | bと同等 |
+= | 10 進数 | a += b は a:= a + bと同等 |
-= | 10 進数 | a-= b は a := a-b と同等 |
*= | 10 進数 | a *= b は a := a * b と同等 |
/= | 10 進数 | 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 := 30; // Variable of type decimal. var address := record.address; // Variable of an immutable complex. const MAX_AGE := 100; // Decimal constant. const DEFAULT_COUNTRY := 'France'; // String constant. 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 : decimal; age := 30; var address : typeof record.address; address := record.address; const MAX_AGE : decimal := 100; const DEFAULT_COUNTRY : string := 'France'; end |
初期化されていない変数の値は null です。
begin var firstName : string; if isNull(fistName) then do_something(); // 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 age : decimal := 'test'; 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 := record.OfficeAddress; // Declaration using typeof notation. var address2 : typeof record.OfficeAddress; address2 := address1; |
各ステップ (ドットで区切られた部分) は 識別子です。これは、次の引用表記をどのステップにも使用できることを意味します。
var city := record."OfficeAddress".City; |
これは、予約済みのキーワードに相当するステップや、マイナス文字 ( - ) やドット ( . )などの引用符で囲まれていない識別子と互換性のない文字を使用するステップに役立ちます。
実行時に、どのステップも null と評価される可能性があります。この場合、完全なフィールド式は null と評価されます。
複数値フィールドは、順序付きリストとして扱われます。インデックス表記 [index] は、リストの項目にアクセスするために使用されます。インデックスは 0 ベースです (最初のインデックスは 0)。
次の例では、フィールド「Address」は複数値です。
var city := record.Address[1].City; |
インデックスが範囲外の場合、インデックス付きの式は null を返します。この場合、完全なフィールド式は null と評価されます。
インデックスは 10 進式の場合があります。式の整数部分のみが使用されます。
事前定義された変数により、コンテキストへのアクセスが可能になります。これらのコンテキスト変数は定数であり、不変の複合型です。
事前定義された変数 record は、現在のスクリプトがテーブルの関数フィールド用である場合にのみ使用できます。現在のレコードへの読み取り専用アクセスを許可します。
そのフィールドは、現在の EBX® スキーマによって定義されています。
例
// Returns the full name. export function getValue(): string begin return record.FirstName | ' ' | record.LastName; end |
事前定義された変数 root は、現在のスクリプトがデータセットの関数インスタンスフィールド用である場合にのみ使用できます。現在のデータセットのインスタンスフィールドへの読み取り専用アクセスを提供します。
そのフィールドは、現在の EBX® スキーマによって定義されています。
例
// Returns information on current dataset data. export function getValue(): string begin return root.City | ' ' | root.Region; end |
事前定義された変数 dataspace は、現在のデータスペースに関する情報へのアクセスを提供します。
この変数には次のフィールドがあります。
名前 | タイプ | 説明 |
---|---|---|
name | 文字列 | データスペースの名前。データスペースの名前空間とスナップショットの名前空間は独立しているため、返される文字列は名前空間の 1 つのコンテキストにおける識別子にすぎません。グローバル データスペースまたはスナップショット識別子には、フィールド id を使用します。 |
id | 文字列 | データスペースまたはスナップショットの永続的な識別子。name と比較すると、この識別子は、この ID がデータスペース用かスナップショット用かをさらに指定します。 |
isSnapshot | ブール値 | データスペースがスナップショットの場合は true であり、データスペースがブランチの場合は false です。 |
例
// Returns details on the current dataspace. export function getValue(): string begin if dataspace.isSnapshot then return 'Snapshot: ' | dataspace.name; else return 'Branch: ' | dataspace.name; end |
事前定義された変数 dataset は、現在のデータセットに関する情報へのアクセスを提供します。
この変数には次のフィールドがあります。
名前 | タイプ | 説明 |
---|---|---|
name | 文字列 | データセットの名前 |
例
// Returns the current dataset name. export function getValue(): string begin return dataset.name; 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 |
関数の最後のステートメントは常に 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 |
エクスポートされた関数は、EBX® から直接呼び出すことができます。
スクリプトごとに許可されるエクスポートされた関数は 1 つだけです。そのシグネチャ (名前、および戻り型) は、関数フィールドの型によって異なります。
レコードのフィールドの場合、定義は次のようにする必要があります。
export function getValue(): typeof record.<path> begin ... end |
データセットのフィールドの場合、定義は次のようにする必要があります。
export function getValue(): typeof root.<path> begin ... end |
関数フィールドが最初に編集される場合、EBX® はエクスポートされた関数の正しい定義を備えた初期スクリプトを提供します。
プロシージャは、値を返さないメソッドです。
パラメーターのないプロシージャの構文は次のとおりです。
procedure procedure_name() begin .... end |
パラメーターを使用するプロシージャの構文は次のとおりです。
procedure procedure_name( parameter_1 : parameter_1_type, parameter_2 : parameter_2_type...) begin .... end |
プロシージャに return ステートメントを含めることはできませんが、関数には必要な数の return ステートメントを含めることができます。プロシージャステートメントは値を返すことができません。
単純型パラメーターは値によって渡されます。これは、関数またはプロシージャが元の値のコピーを受け取ることを意味します。
複合型とリスト型は参照によって渡されます。これは、関数またはプロシージャが元のオブジェクトを受け取ることを意味します。関数またはプロシージャがオブジェクトを変更すると、元のオブジェクトが変更されます。
「if then」ステートメントの構文は次のとおりです。
if condition-expression then then-statement |
条件式はブール型として評価される必要があります。
「then」ステートメントは ステートメントブロックにすることができます。
「if then else」ステートメントの構文は次のとおりです。
if condition-expression then then-statement else else-statement |
条件式はブール型にする必要があります。
「then」または「else」ステートメントは、ステートメントブロックにすることができます。
注意
式
if condition-expression then statements-a; else statements-b; |
次のように指定することはできません。
if not condition-expression then statements-b; else statements-a; |
実際、式が null の場合、どちらの場合も else ステートメントが実行されます。
「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 record.Addresses do begin if cities <> '' then cities |= ', '; cities |= address.city; end |
「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 |
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 record.Cities begin return list.of('Paris', 'Bruxelles', 'Berlin'); end |
提供されているユニットの詳細については、API ドキュメントを参照してください。
ユニット unit.log は、メッセージをログに記録するために使用できる関数を提供します。
スクリプトによってログに記録されたメッセージは、[管理] > [リポジトリ管理] > [スクリプト] の EBX® メニューを使用して表示できます。
もう 1 つの便利な機能は、スクリプトの実行中にランタイムでエラーが発生した場合、通常、エラーが発生したスクリプトの行とともにログに記録されることです。
DMA を使用して新しい関数フィールドが作成されると、初期スクリプトが作成されます。
次の例は、文字列型のフィールド用に作成されたスクリプトです。
export function getValue(): string begin return 'A string value'; end |
エクスポートされた関数シグネチャ (名前と戻り値の型) はフィールドの型によって異なるため、変更しないでください。