149 lines
5.1 KiB
MySQL
149 lines
5.1 KiB
MySQL
-- Deterministic daily-AU lookup for an already resolved game query plan.
|
|
-- Physical user-master objects are selected only from SG_GAME_CATALOG.
|
|
-- No game name, alias, prefix, or object name is embedded in this function.
|
|
|
|
CREATE OR REPLACE FUNCTION sg_game_daily_au_lookup(
|
|
p_query_plan IN CLOB,
|
|
p_base_date IN DATE DEFAULT NULL
|
|
) RETURN CLOB AUTHID DEFINER IS
|
|
v_plan JSON_OBJECT_T;
|
|
v_targets JSON_ARRAY_T;
|
|
v_target JSON_OBJECT_T;
|
|
v_result JSON_OBJECT_T := JSON_OBJECT_T();
|
|
v_items JSON_ARRAY_T := JSON_ARRAY_T();
|
|
v_item JSON_OBJECT_T;
|
|
v_game_key VARCHAR2(128);
|
|
v_game_id VARCHAR2(128);
|
|
v_game_name VARCHAR2(512);
|
|
v_object_name VARCHAR2(128);
|
|
v_safe_object_name VARCHAR2(128);
|
|
v_effective_date DATE;
|
|
v_au_count NUMBER;
|
|
v_column_count PLS_INTEGER;
|
|
v_object_count PLS_INTEGER;
|
|
v_seen SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST();
|
|
v_target_count PLS_INTEGER := 0;
|
|
|
|
FUNCTION is_seen(p_game_key IN VARCHAR2) RETURN BOOLEAN IS
|
|
BEGIN
|
|
FOR i IN 1 .. v_seen.COUNT LOOP
|
|
IF v_seen(i) = p_game_key THEN
|
|
RETURN TRUE;
|
|
END IF;
|
|
END LOOP;
|
|
RETURN FALSE;
|
|
END;
|
|
|
|
PROCEDURE add_status(
|
|
p_game_key IN VARCHAR2,
|
|
p_status IN VARCHAR2,
|
|
p_reason IN VARCHAR2
|
|
) IS
|
|
BEGIN
|
|
v_item := JSON_OBJECT_T();
|
|
v_item.put('gameKey', p_game_key);
|
|
v_item.put('status', p_status);
|
|
v_item.put('reason', p_reason);
|
|
v_items.append(v_item);
|
|
END;
|
|
BEGIN
|
|
IF p_query_plan IS NULL THEN
|
|
RAISE_APPLICATION_ERROR(-20001, 'queryPlan is required');
|
|
END IF;
|
|
|
|
v_plan := JSON_OBJECT_T.parse(p_query_plan);
|
|
v_targets := v_plan.get_array('dataEligibleTargets');
|
|
IF v_targets IS NULL THEN
|
|
v_targets := v_plan.get_array('targets');
|
|
END IF;
|
|
|
|
IF v_targets IS NOT NULL AND v_targets.get_size > 0 THEN
|
|
FOR i IN 0 .. v_targets.get_size - 1 LOOP
|
|
v_target := TREAT(v_targets.get(i) AS JSON_OBJECT_T);
|
|
IF v_target IS NULL OR NOT v_target.has('gameKey') THEN
|
|
CONTINUE;
|
|
END IF;
|
|
v_game_key := v_target.get_string('gameKey');
|
|
IF v_game_key IS NULL OR is_seen(v_game_key) THEN
|
|
CONTINUE;
|
|
END IF;
|
|
v_seen.EXTEND;
|
|
v_seen(v_seen.COUNT) := v_game_key;
|
|
v_target_count := v_target_count + 1;
|
|
|
|
BEGIN
|
|
SELECT game_id, game_nm, user_master_object_name
|
|
INTO v_game_id, v_game_name, v_object_name
|
|
FROM sg_game_catalog
|
|
WHERE game_key = v_game_key
|
|
AND active_yn = 'Y';
|
|
EXCEPTION
|
|
WHEN NO_DATA_FOUND THEN
|
|
add_status(v_game_key, 'UNAVAILABLE', 'Catalog target is not active.');
|
|
CONTINUE;
|
|
END;
|
|
|
|
IF v_object_name IS NULL THEN
|
|
add_status(v_game_key, 'UNAVAILABLE', 'No approved user-master object is registered.');
|
|
CONTINUE;
|
|
END IF;
|
|
|
|
v_safe_object_name := DBMS_ASSERT.SIMPLE_SQL_NAME(UPPER(v_object_name));
|
|
SELECT COUNT(*) INTO v_object_count
|
|
FROM user_objects
|
|
WHERE object_name = v_safe_object_name
|
|
AND object_type IN ('TABLE', 'VIEW', 'MATERIALIZED VIEW')
|
|
AND status = 'VALID';
|
|
SELECT COUNT(*) INTO v_column_count
|
|
FROM user_tab_columns
|
|
WHERE table_name = v_safe_object_name
|
|
AND column_name IN ('GUID', 'BASE_DT', 'AU_FLAG', 'EXPT_USER_YN');
|
|
IF v_object_count = 0 OR v_column_count <> 4 THEN
|
|
add_status(v_game_key, 'UNAVAILABLE', 'Approved user-master object is not query-ready.');
|
|
CONTINUE;
|
|
END IF;
|
|
|
|
IF p_base_date IS NULL THEN
|
|
EXECUTE IMMEDIATE 'SELECT MAX(BASE_DT) FROM ' || v_safe_object_name
|
|
INTO v_effective_date;
|
|
ELSE
|
|
v_effective_date := TRUNC(p_base_date);
|
|
END IF;
|
|
IF v_effective_date IS NULL THEN
|
|
add_status(v_game_key, 'NO_DATA', 'No available base date in the selected object.');
|
|
CONTINUE;
|
|
END IF;
|
|
|
|
EXECUTE IMMEDIATE
|
|
'SELECT COUNT(DISTINCT GUID) FROM ' || v_safe_object_name
|
|
|| ' WHERE BASE_DT = :1 AND AU_FLAG = 1 AND EXPT_USER_YN = ''N'''
|
|
INTO v_au_count USING v_effective_date;
|
|
|
|
v_item := JSON_OBJECT_T();
|
|
v_item.put('gameKey', v_game_key);
|
|
v_item.put('gameId', v_game_id);
|
|
v_item.put('gameName', v_game_name);
|
|
v_item.put('objectName', v_safe_object_name);
|
|
v_item.put('baseDate', TO_CHAR(v_effective_date, 'YYYY-MM-DD'));
|
|
v_item.put('auCount', v_au_count);
|
|
v_item.put('status', 'READY');
|
|
v_item.put('sqlTemplate',
|
|
'SELECT COUNT(DISTINCT GUID) AS AU_COUNT FROM <catalog_user_master_object> '
|
|
|| 'WHERE BASE_DT = :baseDate AND AU_FLAG = 1 AND EXPT_USER_YN = ''N''');
|
|
v_items.append(v_item);
|
|
END LOOP;
|
|
END IF;
|
|
|
|
v_result.put('status', CASE WHEN v_target_count = 0 THEN 'NO_GAME_TARGET' ELSE 'GAME_AU_LOOKUP' END);
|
|
v_result.put('targetType', NVL(v_plan.get_string('targetType'), 'NONE'));
|
|
IF p_base_date IS NULL THEN
|
|
v_result.put_null('requestedBaseDate');
|
|
ELSE
|
|
v_result.put('requestedBaseDate', TO_CHAR(TRUNC(p_base_date), 'YYYY-MM-DD'));
|
|
END IF;
|
|
v_result.put('targetCount', v_target_count);
|
|
v_result.put('items', v_items);
|
|
RETURN v_result.to_clob;
|
|
END;
|
|
/
|