Сохранение данных в LAS формат
CREATE OR REPLACE FUNCTION public.func_core_save_to_las(
a_user_id integer,
a_parameters jsonb DEFAULT NULL::jsonb)
RETURNS jsonb
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
AS $BODY$
DECLARE
v_las_content text := '';
v_well_info jsonb;
v_curve_info jsonb;
v_log_data jsonb;
v_wrap_mode text := 'NO';
v_null_value text := '-999.25';
v_start_depth numeric;
v_stop_depth numeric;
v_step numeric;
BEGIN
-- Начало выполнения функции
RAISE NOTICE 'func_core_save_to_las: Начало выполнения (user_id: %, parameters: %)', a_user_id, a_parameters;
-- Извлекаем информацию из параметров
v_well_info := a_parameters->'well_info';
v_curve_info := a_parameters->'curve_info';
v_log_data := a_parameters->'log_data';
-- Получаем параметры глубины
v_start_depth := (v_well_info->>'start_depth')::numeric;
v_stop_depth := (v_well_info->>'stop_depth')::numeric;
v_step := (v_well_info->>'step')::numeric;
-- Определяем режим переноса (если много кривых, используем WRAP YES)
IF jsonb_array_length(v_curve_info) > 10 THEN
v_wrap_mode := 'YES';
END IF;
-- Формируем заголовок LAS файла
-- 1. Секция Version Information
v_las_content := v_las_content || '~VERSION INFORMATION' || E'\n';
v_las_content := v_las_content || 'VERS. 2.1 : CWLS LOG ASCII STANDARD - VERSION 2.1' || E'\n';
v_las_content := v_las_content || 'WRAP. ' || v_wrap_mode || ' : ' ||
CASE WHEN v_wrap_mode = 'YES' THEN 'Multiple lines per depth step'
ELSE 'One line per depth step' END || E'\n';
v_las_content := v_las_content || E'\n';
-- 2. Секция Well Information
v_las_content := v_las_content || '~WELL INFORMATION' || E'\n';
v_las_content := v_las_content || '#MNEM.UNIT VALUE DESCRIPTION' || E'\n';
v_las_content := v_las_content || '#-------- ---------- ---------------------' || E'\n';
v_las_content := v_las_content || 'STRT .' || (v_well_info->>'depth_unit') || ' ' ||
to_char(v_start_depth, 'FM999999990.0000') || ' : START DEPTH' || E'\n';
v_las_content := v_las_content || 'STOP .' || (v_well_info->>'depth_unit') || ' ' ||
to_char(v_stop_depth, 'FM999999990.0000') || ' : STOP DEPTH' || E'\n';
v_las_content := v_las_content || 'STEP .' || (v_well_info->>'depth_unit') || ' ' ||
to_char(v_step, 'FM999999990.0000') || ' : STEP' || E'\n';
v_las_content := v_las_content || 'NULL . ' || v_null_value || ' : NULL VALUE' || E'\n';
v_las_content := v_las_content || 'COMP . ' || (v_well_info->>'company') || ' : COMPANY' || E'\n';
v_las_content := v_las_content || 'WELL . ' || (v_well_info->>'well_name') || ' : WELL' || E'\n';
v_las_content := v_las_content || 'FLD . ' || (v_well_info->>'field') || ' : FIELD' || E'\n';
v_las_content := v_las_content || 'LOC . ' || (v_well_info->>'location') || ' : LOCATION' || E'\n';
v_las_content := v_las_content || 'PROV . ' || (v_well_info->>'province') || ' : PROVINCE' || E'\n';
v_las_content := v_las_content || 'SRVC . ' || (v_well_info->>'service_company') || ' : SERVICE COMPANY' || E'\n';
v_las_content := v_las_content || 'DATE . ' || (v_well_info->>'log_date') || ' : LOG DATE' || E'\n';
v_las_content := v_las_content || 'UWI . ' || (v_well_info->>'unique_well_id') || ' : UNIQUE WELL ID' || E'\n';
v_las_content := v_las_content || E'\n';
-- 3. Секция Curve Information
v_las_content := v_las_content || '~CURVE INFORMATION' || E'\n';
v_las_content := v_las_content || '#MNEM.UNIT API CODE CURVE DESCRIPTION' || E'\n';
v_las_content := v_las_content || '#----------- ----------- ------------------------------' || E'\n';
-- Добавляем кривые из параметров
FOR i IN 0..jsonb_array_length(v_curve_info)-1 LOOP
DECLARE
v_curve jsonb := v_curve_info->i;
BEGIN
v_las_content := v_las_content ||
rpad((v_curve->>'mnemonic')::text, 8) || '.' ||
rpad((v_curve->>'unit')::text, 8) || ' ' ||
rpad(COALESCE((v_curve->>'api_code')::text, ''), 12) || ' : ' ||
(v_curve->>'description')::text || E'\n';
END;
END LOOP;
v_las_content := v_las_content || E'\n';
-- 4. Секция Parameter Information (необязательная)
IF a_parameters ? 'parameter_info' THEN
v_las_content := v_las_content || '~PARAMETER INFORMATION' || E'\n';
v_las_content := v_las_content || '#MNEM.UNIT VALUE DESCRIPTION' || E'\n';
FOR i IN 0..jsonb_array_length(a_parameters->'parameter_info')-1 LOOP
DECLARE
v_param jsonb := (a_parameters->'parameter_info')->i;
BEGIN
v_las_content := v_las_content ||
rpad((v_param->>'mnemonic')::text, 8) || '.' ||
rpad(COALESCE((v_param->>'unit')::text, ''), 8) || ' ' ||
rpad((v_param->>'value')::text, 16) || ' : ' ||
(v_param->>'description')::text || E'\n';
END;
END LOOP;
v_las_content := v_las_content || E'\n';
END IF;
-- 5. Секция данных (~A)
v_las_content := v_las_content || '~A' || E'\n';
-- Добавляем данные каротажа
IF v_wrap_mode = 'NO' THEN
-- Режим без переноса - одна строка на точку
FOR i IN 0..jsonb_array_length(v_log_data)-1 LOOP
DECLARE
v_data_point jsonb := v_log_data->i;
v_line text := '';
BEGIN
-- Добавляем значения всех кривых для текущей глубины
FOR j IN 0..jsonb_array_length(v_curve_info)-1 LOOP
DECLARE
v_curve jsonb := v_curve_info->j;
v_mnemonic text := v_curve->>'mnemonic';
v_value text;
BEGIN
IF j > 0 THEN
v_line := v_line || ' ';
END IF;
IF v_data_point ? v_mnemonic THEN
v_value := (v_data_point->>v_mnemonic)::text;
ELSE
v_value := v_null_value;
END IF;
v_line := v_line || v_value;
END;
END LOOP;
v_las_content := v_las_content || v_line || E'\n';
END;
END LOOP;
ELSE
-- Режим с переносом - сначала глубина, затем значения
FOR i IN 0..jsonb_array_length(v_log_data)-1 LOOP
DECLARE
v_data_point jsonb := v_log_data->i;
v_depth text := (v_data_point->>(v_curve_info->0->>'mnemonic'))::text;
v_line text := '';
v_values_per_line integer := 5; -- Количество значений в строке
BEGIN
-- Строка с глубиной
v_las_content := v_las_content || v_depth || E'\n';
-- Строки со значениями (по v_values_per_line значений в строке)
FOR j IN 1..jsonb_array_length(v_curve_info)-1 LOOP
DECLARE
v_curve jsonb := v_curve_info->j;
v_mnemonic text := v_curve->>'mnemonic';
v_value text;
BEGIN
IF (j-1) % v_values_per_line = 0 THEN
IF j > 1 THEN
v_las_content := v_las_content || v_line || E'\n';
END IF;
v_line := '';
ELSE
v_line := v_line || ' ';
END IF;
IF v_data_point ? v_mnemonic THEN
v_value := (v_data_point->>v_mnemonic)::text;
ELSE
v_value := v_null_value;
END IF;
v_line := v_line || v_value;
END;
END LOOP;
-- Добавляем последнюю строку значений
IF length(v_line) > 0 THEN
v_las_content := v_las_content || v_line || E'\n';
END IF;
END;
END LOOP;
END IF;
-- Возвращаем результат в формате LAS
RETURN jsonb_build_object(
'msg', 'ok',
'las_content', v_las_content,
'las_format', 'LAS 2.1'
);
EXCEPTION
WHEN OTHERS THEN
-- Ошибка выполнения функции
RAISE WARNING 'func_core_save_to_las: Ошибка (user_id: %): %', a_user_id, SQLERRM;
RETURN jsonb_build_object(
'msg', 'error',
'error', 'Ошибка func_core_save_to_las: ' || SQLERRM
);
END;
$BODY$;
ALTER FUNCTION public.func_core_save_to_las(integer, jsonb)
OWNER TO core;