2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CDS Scalar Functionsを使って独自の関数を定義する

Last updated at Posted at 2024-10-05

はじめに

以下の記事で、CDS Viewの日付項目と実行日の差を計算する方法を紹介しました。このような計算はほかのViewでも使う可能性があるので、再利用する方法について考えます。

一つ目の方法は、以下の記事で紹介したCDS Aspectsです。

この記事では、CDS Scaler Functionを使って同じことを実現してみます。

CDS Scaler Function

CDS Scaler Functionは、CDS Viewの中で使うファンクションを独自に定義するものです。SAP BTP ABAP environment 2208およびSAP S/4HANA Cloud 2208から利用できるようになりました。
Version 3.28 | What's New

ファンクションは以下のようにして呼び出すことができます。

ファンクションの呼び出し方法
function_name(param1 => <設定値>, param2 => <設定値>) as Field1,

CDS Scaler Functionについて、以下の動画で紹介されていました。
Data Modeling with the latest features of ABAP Core Data Services | Youtube

CDS Scalar Functionsで日付項目と実行日の差を計算する関数を作る

Aspectを使用する前のViewの定義は以下のようになっています。

@AccessControl.authorizationCheck: #CHECK
@Metadata.allowExtensions: true
@EndUserText.label: '###GENERATED Core Data Service Entity'
define root view entity ZR_TODO
  as select from ztodo as Todo
{
  key id as Id,
  title as Title,
  detail as Detail,
  due_date as DueDate,
  
  //計算項目
  tstmp_current_utctimestamp() as TimeStampToday,
  tstmp_to_dats($projection.TimeStampToday, 'JAPAN', $session.client, 'NULL') as DateToday,
  dats_days_between($projection.DateToday, $projection.DueDate) as DateDifference,
  
  case
    when $projection.DateDifference < 0 then 1 //negative: overdue
    when $projection.DateDifference < 3 then 2 //critical
    else 3 end as Criticality, 
  //
  
  @Semantics.user.createdBy: true
  created_by as CreatedBy,
  @Semantics.systemDateTime.createdAt: true
  created_at as CreatedAt,
  @Semantics.user.localInstanceLastChangedBy: true
  last_changed_by as LastChangedBy,
  @Semantics.systemDateTime.localInstanceLastChangedAt: true
  local_last_changed_at as LocalLastChangedAt,
  @Semantics.systemDateTime.lastChangedAt: true
  last_changed_at as LastChangedAt
}

以下のステップでCDS Scalar Functionを作成し、それを元のCDS Viewに組み込みます。

  1. Scaler Functionの定義
  2. AMDPクラスの定義
  3. Scaler Function Implementation Referenceの定義
  4. AMDPクラスの実装
  5. CDS ViewでScalar Functionを利用

BTP ABAP Environment(トライアル)で検証を行っています。

1. Scaler Functionの定義

Core Data Services > Scaler Function Definition を選択します。
image.png

名前は最大26桁で、2番目と3番目の位置にアンダースコアがあってはいけないという制約があります。
image.png

初期状態は以下のようになっています。
image.png

以下のようにScaler Functionを定義しました。

define scalar function ZDATE_DIFF_FROM_TODAY
  with parameters
    timezone_in: zde_timezone_hana,
    target_date: abap.dats
  returns abap.int2

zde_timezone_hanaというデータエレメントにはHANAで定義されているタイムゾーンを指定するため、CHAR 64桁でCase-sensitiveなドメインを定義して使用しています。
image.png

2. AMDPクラスの定義

CDS Scaler FunctionのロジックはAMDPで実装します。Interface: IF_AMDP_MARKER_HDBを実装したクラスを定義します。
image.png

以下の状態で有効化します。
image.png

3. Scaler Function Implementation Referenceの定義

Scaler Functionを右クリックし、"New Scaler Function Implementation Reference"を選択します。
image.png

CDS Viewから呼び出す場合、Engineに"SQL Engine"を選択します。分析クエリから呼び出す場合は"Analytical Engine"を選択します。選択したエンジンに応じて、名前の末尾に"_SQL"または、"_ANA"をつける必要があります。
image.png

AMDP Referenceに2.で定義したクラスと、メソッド(未実装)を指定します。ワーニングが出ますが、有効化できます。(メソッド実装後に再有効化が必要)
image.png

4. AMDPクラスの実装

Implementation Referenceで指定したexecuteというメソッドを定義します(メソッド名はImplementation Referenceと一致していればなんでもよい)。

Implementation Referenceを先に定義しておかないと、zdate_diff_from_todayというScaler Functionが見つからないというエラーになります。

CLASS zcl_date_diff_from_today_amdp DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.

    INTERFACES if_amdp_marker_hdb .

    CLASS-METHODS execute
        FOR SCALAR FUNCTION zdate_diff_from_today.

  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

メソッドの実装は以下のようになります。

CLASS zcl_date_diff_from_today_amdp IMPLEMENTATION.
  METHOD execute BY DATABASE FUNCTION FOR HDB LANGUAGE SQLSCRIPT.
    declare utc_timestamp timestamp;
    declare local_timestamp timestamp;

    -- today
    SELECT current_utctimestamp INTO utc_timestamp FROM dummy;
    SELECT utctolocal(:utc_timestamp, :timezone_in) AS local_timestamp INTO local_timestamp FROM dummy;

    -- date difference
    SELECT days_between(to_date(:local_timestamp), to_date(:target_date)) AS days_between INTO result FROM dummy;
  ENDMETHOD.

ENDCLASS.

このメソッドでは以下の計算を行っています。

4.1. 現在の日付を取得する

タイムゾーンを考慮した日付を取得するため、はじめに現在のタイムスタンプを取得し、それを日付型に変換します。

①現在のタイムスタンプを取得する

    SELECT current_utctimestamp INTO utc_timestamp FROM dummy;

CURRENT_UTCTIMESTAMPというファンクションで、現在のUTCのタイムスタンプを取得します。
出力例:2024-10-05 20:55:33.965000000

②タイムスタンプを指定したタイムゾーンに変換する

    SELECT utctolocal(:utc_timestamp, :timezone_in) AS local_timestamp INTO local_timestamp FROM dummy;

UTCTOLOCALというファンクションで、UTCのタイムスタンプを第二引数で指定したタイムゾーンでのタイムスタンプに変換します。タイムゾーンには、Scaler Functionのインプットである"timezone_in"を指定しています。
出力例:2024-10-06 05:55:33.965000000

指定可能なタイムゾーンはシステムビュー:TIMEZONESで確認できます。ABAP側で利用するタイムゾーンの値とは異なることに注意が必要です(ABAPの場合、日本は大文字の'JAPAN')。
image.png

4.2. 指定された日付との差を計算する

    SELECT days_between(to_date(:local_timestamp), to_date(:target_date)) AS days_between INTO result FROM dummy;

DAYS_BETWEEN(date1, date2)というファンクションで、date2からdate1を引いた日数を計算します。TO_DATE()というファンクションは、指定された日付のストリングをDAYDATE型(YYYY-MM-DD)に変換します。
最後に計算結果を格納しているresultという項目は、Scaler Functionの返り値です。

以下はDatabase Explorerで動作確認した結果です。AMDPはCDS Viewに組み込むまで正しく動くかがわからないので、事前に確認するためにはDatabase Explorerが便利でした。S/4HANAに固有なテーブルはここでは使えませんが、ファンクションなどの動きを確認するのには役立ちます。
image.png

5. CDS ViewでScalar Functionを利用

CDS Viewで利用可能にするために、AMDPメソッドを実装したあとでScaler Function Implementation Referenceを再有効化する必要があります。

CDS Viewにもともとあった計算項目をコメントアウトし、Scaler Functionを追加します。
image.png

Scaler Functionが"zde_timezone_hana"という型でタイムゾーンを受け取るため、リテラルをその型に変換しています。

  cast('Japan' as zde_timezone_hana) as TimeZoneHana,

以下でScaler Functionを呼び出しています。

    ZDATE_DIFF_FROM_TODAY( timezone_in => $projection.TimeZoneHana, 
                        target_date => $projection.DueDate ) as DateDifference,

プレビューで見ると、"DateDifference"が正しく計算されています。
image.png

Scaler Functionと比較して

CDS Scaler Functionsの場合、最終結果に必要ない項目も計算のために持たなければなりませんが、CDS Scaler Functionsは結果のみ返すので、今回の目的にはより合っています。
ただし、ファンクションの実装をAMDP(SQL Script)で書く必要があるので、CDS Scaler Functionsに比べ実装は難しかったです。

参考

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?