新しい LookML ランタイムへの移行

Looker の新しい LookML ランタイムは、Looker 22.6 以降で利用できます。「ランタイム」は、LookML コードを解釈する Looker の一部です。新しいランタイムは高速化され、従来のランタイムよりも多くの LookML エラーが確認されます。

Looker では、2025 年初頭にすべてのお客様が新しいランタイムに移行することを必須としており、すべてのお客様に対して、その前に移行を完了しておくことを強く推奨しています。新しい LookML ランタイムでは、以前に見落とされていたエラーを検出できるため、新しいランタイムを有効にすると、新しい LookML エラーが表示されることがあります。これらのエラーは、新しいランタイムに起因するものではありません。新たに検出できるようになった既存のエラーです。

また、インスタンスを Looker(Google Cloud コア)に変更する場合は、事前に新しいランタイムに移行する必要があります。

新しいランタイムに切り替える方法

1. 可能であれば、[以前の LookML ランタイムを使用する] レガシー機能をオフにします。

一部の Looker では、以前の LookML ランタイムを使用するレガシー機能が有効になっています。[以前の LookML ランタイムを使用する] レガシー機能を無効にして、Looker インスタンスを新しいランタイムに移行します。

Looker インスタンスの [レガシー機能] 管理ページで [以前の LookML ランタイムを使用する] レガシー機能が使用できない場合、インスタンスはすでに新しいランタイムを使用しています。

2. LookML プロジェクトが new_lookml_runtime:no で構成されていないことを確認する

Looker インスタンスのグローバルな [以前の LookML ランタイムを使用する] 設定をオーバーライドするには、LookML プロジェクトのマニフェスト ファイルnew_lookml_runtime:no ステートメントを追加します。

LookML プロジェクトのマニフェスト ファイルに new_lookml_runtime パラメータがない、またはすべての LookML プロジェクトで new_lookml_runtimeyes に設定されていることを確認します。

新しいランタイムで検出される可能性のある LookML の問題

新しいランタイムに移行すると、LookML に新しいエラーが表示されることがあります。この新しいエラーは、新しいランタイムに起因するものではありません。新たに検出できるようになった既存の問題です。

LookML デベロッパーの設定によっては、LookML の変更の送信を続行する前に、これらのエラーを修正する必要があります。以下のセクションでは、新しい LookML ランタイムによってプロジェクトで検出される可能性のある問題と、その解決方法について説明します。

Liquid 式内のより厳密なタイプチェック

Liquid 内の値を比較する場合、新しいランタイムでは、2 つの値が同じタイプである必要があります。このエラーは、10 進数が整数値と比較されている場合によく発生します。

この例では、ある製品の購入者の平均年齢を下回っている場合、または上回っている場合、Liquid を使用してユーザーの年齢を色分けしています。

dimension: age {
  type: integer
  html:
    {% dynamic if value > product.average_age._value %}
      <div style="color:orange">{{rendered_value}}</div>
    {% dynamic else %}
      <div style="color:blue">{{rendered_value}}</div>
    {% dynamic endif %}
    ;;
}

average_age は 10 進数で、年齢は整数であるため、新しいランタイムはエラーを検出します。assign 式を乗算フィルタと組み合わせて、整数を 10 進数に変更します。

dimension: age {
  sql: ${TABLE}.age
  type: integer
  html:
    {% assign dec_value = value |times(1.0) %}
    {% dynamic if dec_value > product.average_age._value %}
      <div style="color:orange">{{rendered_value}}</div>
    {% dynamic else %}
      <div style="color:blue">{{rendered_value}}</div>
    {% dynamic endif %}
    ;;
}

未定義値の異なる処理

以前のランタイムは未定義値を NULL に変換しますが、新しいランタイムでは例外をスローします。この例では、ディメンションは値のカンマ区切りリストで 2 番目の値を表示しようとしています。

dimension: second_flag {
  sql: ${TABLE}.flag_list
  type: string
  html:
    {% assign flag_values = value |split(",") %}
    {% dynamic if flag_values[1] %}
      {{ flag_values[1] }}
    {% dynamic else %}
      No second flag
    {% dynamic endif %}
    ;;
}

これは、以前のランタイムでは機能します。一部のケースでは flag_values[1] が未定義で NULL に変換され、その後 Liquid が解釈される可能性があるためです。ただし、新しいランタイムでは、flag_values[1] は未定義のままになります。

この問題に対処するには、nil を明示的に確認します。

dimension: second_flag {
  sql: ${TABLE}.flag_list
  type: string
  html:
    {% assign flag_values = value |split(",") %}
    {% dynamic if flag_values[1] != nil %}
      {{ flag_values[1] }}
    {% dynamic else %}
      No second flag
    {% dynamic endif %}
    ;;
}

一部の永続的な派生テーブルが再構築される場合がある

永続的な派生テーブル(PDT)キーは、LookML ランタイムによって生成された SQL に基づいています。場合によっては、新しいランタイムでは PDT に異なる(ただし同等の)SQL が生成され、異なる PDT キーが生成されることがあります。PDT キーを変更すると、PDT が再構築されます。

Liquid 式内の HTML リテラルが Unicode に変換される場合がある

Liquid 式内の HTML タグは、新しいランタイムによって対応する Unicode に変換されることがあります。たとえば、<strong> タグが &lt;strong&gt; に変換されることがあります。以前のランタイムの HTML タグは、次の例のように、直接比較できます。

html:
  {{ value |replace("<strong>"), "[" |replace("</strong>"), "]" }} ;;

新しいランタイムの比較では、代わりに Unicode に対して比較する必要があります。

html:
  {{ value |replace("&lt;strong&gt;"), "[" |replace("&lt;/strong&gt;"), "]" }} ;;

sql_distinct_key 内の無効な参照は「不明なビュー」になる

新しいランタイムでは、不明なフィールドまたはビューを参照する sql_distinct_key によって例外がスローされます。次に例を示します。

measure: total_shipping {
  type: sum_distinct
  sql: ${order_shipping} ;;
  sql_distinct_key: ${some_incorrect_field_name} ;;
}

主キーのない「異なる」タイプの measure によって、異なる SQL が生成される

primary-key または sql_distinct_key パラメータを使用しない異なるタイプの measure(average_distinctcount_distinctmedian_distinctpercentile_distinctsum_distinct)により、新しいランタイムで異なる SQL が生成される場合があります。

異なるタイプの measure を作成する場合は、必ず primary-key または sql_distinct_key を指定します。

ベアフィールド参照で Liquid 内の _filters[] にアクセスすると、参照先フィールドが選択された列として追加される

Looker では、「ベアフィールド参照」は中かっこで囲まれていないものです(たとえば、${users.created_date} ではなく users.created_date)。

_filters Liquid 変数と併用すると、以前のランタイムではベアフィールド参照が無視されます。新しいランタイムでは、SQL クエリにフィールドが追加されます。

たとえば、このディメンションでは users.created_date がベア参照です。

dimension: name {
  html:
    {% dynamic if _filters[users.created_date] != NULL %}
      {{rendered_value}} (created: {{_filters[users.created_date]}})
    {% dynamic else %}
      {{rendered_value}}
    {% dynamic endif %}
    ;;
}

従来のランタイムでは、_filters[users.created_date] は常に無視され、{% dynamic if %} が満たされた場合に 2 番目の条件のみが適用されます。新しいランタイムでは、条件を評価できるように、users.created_date が SQL クエリの SELECT 句に追加されます。

Looker クエリに予期しないフィールドが自動的に追加されると、ユーザーの混乱を招く可能性があるため、ベアフィールド参照は使用せず、代わりに ${field_name} 構文を使用することをおすすめします。