3 疑似列

Oracle Continuous Query Language (Oracle CQL)の疑似列のリファレンスを提供します。疑似列は、問い合せることはできますが、イベントの作成元であるデータの一部ではありません。

3.1 疑似列の概要

疑似列からの選択はできますが、値の変更はできません。疑似列は引数のない関数にも似ています(「関数」を参照)。

Oracle CQLでは、次の疑似列がサポートされています。

3.2 ELEMENT_TIME疑似列

CQLでは、すべてのストリーム・イベントにタイムスタンプが関連付けられています。ELEMENT_TIME疑似列は、ストリーム・イベントのタイムスタンプを返します。ELEMENT_TIME疑似列のデータ型は、Oracle CQLネイティブ・タイプのbigintです。ELEMENT_TIMEから返されるタイムスタンプ値の単位はナノ秒です。

注意:

ELEMENT_TIMEは、Oracle CQLリレーションのメンバーではサポートされません。詳細は、「ストリームとリレーション」を参照してください。

この項の内容は、次のとおりです。

詳細については、以下を参照:

3.2.1 ELEMENT_TIME疑似列の値について

各ストリーム・イベントのELEMENT_TIMEの値は、そのイベントのタイムスタンプです。ストリーム・イベントのタイムスタンプは、ストリームの定義とソースによって異なります。

3.2.1 システム・タイムスタンプ付きストリームの場合のELEMENT_TIME

ソース・ストリームがシステム・タイムスタンプによってタイムスタンプが付けられたストリームの場合、ストリーム・イベントのタイムスタンプはSystem.nanoTime()を計算することで割り当てられます。イベントごとのELEMENT_TIME疑似列により、イベントのタイムスタンプが出力されます。

たとえば、システムによってタイムスタンプが付けられたストリームtktest_S1(c1 integer)が定義されているとします。

select ELEMENT_TIME, to_timestamp(ELEMENT_TIME) from tktest_S1

Input (c1)					Output (timestamp: element_time, to_timestamp(element_time))
10									12619671878392750:+ 12619671878392750,05/26/1970 18:27:51
20									12619671889193750:+ 12619671889193750,05/26/1970 18:27:51
30									12619671890093750:+ 12619671890093750,05/26/1970 18:27:51
40									12619671891399750:+ 12619671891399750,05/26/1970 18:27:51
50									12619671896472750:+ 12619671896472750,05/26/1970 18:27:51

注意:

タイムスタンプはSystem.nanoTime()を計算することで算出されるため、出力は実行ごとに様々であり、マシンによっても異なります。
3.2.1.2 アプリケーション・タイムスタンプ付きストリームの場合のELEMENT_TIME

ソース・ストリームがアプリケーションによってタイムスタンプが付けられたストリームの場合、ストリーム・イベントのタイムスタンプはアプリケーションのタイムスタンプ式を計算することで割り当てられます。計算されたタイムスタンプ値の単位は常にナノ秒になります。ELEMENT_TIME疑似列により、イベントのタイムスタンプが出力されます。

たとえば、アプリケーションによってタイムスタンプが付けられたストリームtktest_S1(C1 integer, c2 bigint)が定義されていて、アプリケーションのタイムスタンプ式がc2*1000000000Lだとします。

select ELEMENT_TIME, to_timestamp(ELEMENT_TIME) from tktest_S1

Input(c1,c2) 	Output(timestamp: element_time, to_timestamp(element_time))
10, 10				10000000000:+ 10000000000,12/31/1969 17:00:10
20, 20				20000000000:+ 20000000000,12/31/1969 17:00:20
30, 30				30000000000:+ 30000000000,12/31/1969 17:00:30
40, 40				40000000000:+ 40000000000,12/31/1969 17:00:40
50, 50				50000000000:+ 50000000000,12/31/1969 17:00:50

前述の問合せでは、各イベントのタイムスタンプは、それぞれのイベントのc2*1000000000Lを計算することで算出されています。ELEMENT_TIMEは、イベントのタイムスタンプと同じであることがわかります。

3.2.1.2.1 intまたはbigintに対して評価を行う派生タイムスタンプ式

派生タイムスタンプ式が、Oracle CQLネイティブ・タイプintに対して評価を行う場合、対応するbigint値として結果が返されます。この式がOracle CQLネイティブ・タイプbigintに対して評価を行う場合は、その値がそのまま返されます。

3.2.1.2.2 timestampに対して評価を行う派生タイムスタンプ式

派生タイムスタンプ式がOracle CQLネイティブ・タイプtimestampに対して評価を行う場合は、この時間値をJanuary 1, 1970, 00:00:00 GMTなど、"Epoch"(エポック)と呼ばれる標準の基本時間以降ののミリ秒として表すことにより、long値に変換されます。

3.2.1.3 インラインCQLビューのELEMENT_TIME

ソース・ストリームがインラインCQLビューから受け取られた場合、ストリーム・イベントのタイムスタンプはビューの問合せによって算出されます。ELEMENT_TIMEにより、イベントのタイムスタンプが出力されます。ELEMENT_TIMEの単位は常にナノ秒になり、データ型はCQLネイティブ・タイプのbigintになります。

たとえば、アプリケーションによってタイムスタンプが付けられたストリームtktest_S1(C1 integer, c2 bigint)が定義されていて、アプリケーションのタイムスタンプ式がc2*1000000000Lだとします。

ビューVは、問合せISTREAM(SELECT * FROM SYSTS_STREAM[RANGE 1 MINUTE SLIDE 15 SECONDS]を使用することで定義されています。

select ELEMENT_TIME, to_timestamp(ELEMENT_TIME) from V
Input(c1,c2)		Output(timestamp: element_time, to_timestamp(element_time))
10, 10				15000000000:+ 15000000000,12/31/1969 17:00:15
20, 20				30000000000:+ 30000000000,12/31/1969 17:00:30
30, 30				30000000000:+ 30000000000,12/31/1969 17:00:30
40, 40				45000000000:+ 45000000000,12/31/1969 17:00:45
50, 50				50000000000:+ 50000000000,12/31/1969 17:00:55
3.2.1.4 副問合せのELEMENT_TIME

ソース・ストリームが副問合せから受け取られた場合、CQLは副問合せの結果に対するELEMENT_TIMEをサポートしません。

次の例は、サポートされないシナリオを示しています。

SELECT ELEMENT_TIME FROM ( ISTREAM(SELECT * FROM SYSTS_STREAM[RANGE 1 HOUR SLIDE 5 MINUTES])

3.2.2 Oracle CQL問合せ内での_TIME疑似列の使用

この項では、様々な問合せでELEMENT_TIMEを使用する方法を説明します。

3.2.2.1 SELECTでのELEMENT_TIMEの使用

次の例は、select文でELEMENT_TIME擬似列を使用する方法を示します。ストリームS1のスキーマは(c1 integer)です。関数to_timestampを使用して、Long値をタイムスタンプ値に変換しています。

<query id="q4"><![CDATA[ 
    select 
        c1, 
        to_timestamp(element_time) 
    from 
        S1[range 10000000 nanoseconds slide 10000000 nanoseconds]
]]></query>
Timestamp   Tuple
 8000       80
 9000       90
13000       130
15000       150
23000       230
25000       250
Timestamp   Tuple Kind  Tuple
 8000       +           80,12/31/1969 17:00:08
 8010       -           80,12/31/1969 17:00:08
 9000       +           90,12/31/1969 17:00:09
 9010       -           90,12/31/1969 17:00:09
13000       +           130,12/31/1969 17:00:13
13010       -           130,12/31/1969 17:00:13
15000       +           150,12/31/1969 17:00:15
15010       -           150,12/31/1969 17:00:15
23000       +           230,12/31/1969 17:00:23
23010       -           230,12/31/1969 17:00:23
25000       +           250,12/31/1969 17:00:25
25010       -           250,12/31/1969 17:00:25

問合せにGROUP BY句が含まれる場合、SELECT文で直接ELEMENT_TIME疑似列を使用することはできません。かわりに、「GROUP BYでのELEMENT_TIMEの使用」で説明するようにビューを使用します。

3.2.2.2 GROUP BYでのELEMENT_TIMEの使用

GROUP BY句があるため、問合せのSELECT文でELEMENT_TIMEを使用することはできません。

<query id="Q1"><![CDATA[ 
    SELECT
        R.queryText AS queryText,
        COUNT(*) AS queryCount
    FROM
        queryEventChannel [range 30 seconds] AS R
    GROUP BY
        queryText
]]></query>

かわりに、ビューを作成します。V1に相当する派生したストリームには、特定のqueryTextグループに対して(queryTextqueryCountmaxTime)が変わるたびに、ストリーム要素が含められます。

<view id="V1"><![CDATA[ 
    ISTREAM (
        SELECT
            R.queryText AS queryText,
            COUNT(*) AS queryCount,
            MAX(R.ELEMENT_TIME) as maxTime
        FROM
            queryEventChannel [range 30 seconds] AS R
        GROUP BY
            queryText
    )
]]></view>

注意:

ビューV1の出力要素に関連付けられている要素時間は、その出力イベントの属性maxTimeの値と同じである必要はありません。

たとえば、ウィンドウがスライドし、 queryEventChannel入力ストリームからの要素がそのウィンドウで期限切れとなった場合に、queryTextグループのqueryCountが変わり、出力となります。ただし、そのウィンドウに入る入力ストリームqueryEventChannelからの新しいイベントがないので、そのウィンドウ内のすべてのイベント間のmaxTimeは変わらず、この出力イベントのmaxTime属性の値は、以前の出力イベントのこの属性値と同じになります。

ただし、出力イベントのELEMENT_TIMEは、出力イベントのELEMENT_TIMEは出力イベントのmaxTime属性の値とは異なるなど、入力ストリームからの最新イベントとは異なり、イベントがウィンドウで期限切れとなった瞬間と同じになります。

ビューV1の出力イベントのELEMENT_TIMEを選択するには、問合せを作成します。

<query id="Q1"><![CDATA[ 
    SELECT
        queryText,
        queryCount,
        ELEMENT_TIME as eventTime
    FROM
        V1
]]></query>
3.2.2.3 PATTERNでのELEMENT_TIMEの使用

次の例は、pattern問合せでELEMENT_TIME疑似列を使用する方法を示します。Nth.statusの値が>= F.statusで、そのタプルのNth.ELEMENT_TIME値と最後にFに一致したタプルとの差がjava.lang.Math.Bigint(Long)として指定された間隔に満たない場合、タプルまたはイベントは相関変数Nthに一致します。

...
PATTERN (F Nth+? L)
        DEFINE
            Nth AS 
                Nth.status >= F.status
                AND 
                Nth.ELEMENT_TIME - F.ELEMENT_TIME < 10000000000L,
            L AS 
                L.status >= F.status 
                AND 
                count(Nth.*) = 3
                AND L.ELEMENT_TIME - F.ELEMENT_TIME < 10000000000L 
...

3.3 ORA_QUERY_ID疑似列

着信イベント分割するには、出力に含まれる問合せ名または識別子の情報が必要になります。クエリの名前または識別子は、タプル属性の一部であり、TupleValueのgetter APIで呼び出すことになります。

この目的のために、Oracle CQLには、問合せの出力に含まれる問合せ名にアクセスする新しい疑似列ORA_QUERY_IDが用意されています。

次に示すように、CQL問合せのSELECTリストで前述の疑似列を使用すると、出力タプルに含まれる問合せ名を取得できます。

CREATE QUERY Q1 AS SELECT ORA_QUERY_ID from STREAM;

前述の問合せQ1の出力イベントごとに、問合せ名または識別子と等しい値を持つ属性が1つのみ含まれます。前述の問合せでは、STREAMへの着信イベントごとに、アプリケーションはQ1の値を保持する1つの属性を含む出力タプルを送信します。

CREATE QUERY Q1 AS
SELECT ORA_QUERY_ID, stock_quote, stock_price FROM StockStream;

次に、入力値と出力値を示します。

Input(stock_quote, stock_price)			Output(ORA_QUERY_ID, stock_quote, stock_price)
ORCL, 34												Q1, ORCL, 34
MSFT, 38												Q1, MSFT, 38
CSCO, 21												Q1, CSCO, 21
INTC, 24												Q1, INTC, 24
FB, 48													Q1, FB, 48