Skip to content

Commit 2cb01b2

Browse files
committed
add missing migration
1 parent bffa88c commit 2cb01b2

1 file changed

Lines changed: 91 additions & 0 deletions

File tree

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
DROP FUNCTION IF EXISTS extract_context_with_highlight(TEXT, TEXT, INT, BOOLEAN);
2+
3+
CREATE OR REPLACE FUNCTION extract_context_with_highlight(
4+
p_text TEXT,
5+
p_substring TEXT,
6+
p_context_lines INT,
7+
p_case_sensitive BOOLEAN DEFAULT FALSE
8+
)
9+
RETURNS TABLE (
10+
match_line_number INT,
11+
snippet_start_line_number INT,
12+
context_snippet TEXT,
13+
match_spans JSONB
14+
)
15+
LANGUAGE plpgsql
16+
AS $$
17+
DECLARE
18+
lines TEXT[];
19+
max_line_num INT;
20+
current_line_num INT;
21+
line_content TEXT;
22+
end_line_num INT;
23+
previous_context TEXT;
24+
flags TEXT;
25+
search_start INT;
26+
match_start_char INT;
27+
match_end_char INT;
28+
line_offset_bytes INT;
29+
BEGIN
30+
lines := regexp_split_to_array(COALESCE(p_text, ''), E'\n');
31+
max_line_num := COALESCE(array_length(lines, 1), 0);
32+
IF max_line_num = 0 THEN
33+
RETURN;
34+
END IF;
35+
36+
flags := CASE WHEN p_case_sensitive THEN '' ELSE 'i' END;
37+
38+
FOR current_line_num IN 1..max_line_num LOOP
39+
line_content := lines[current_line_num];
40+
IF (
41+
(p_case_sensitive AND line_content ~ p_substring)
42+
OR ((NOT p_case_sensitive) AND line_content ~* p_substring)
43+
) THEN
44+
match_line_number := current_line_num;
45+
snippet_start_line_number := GREATEST(1, current_line_num - p_context_lines);
46+
end_line_num := LEAST(max_line_num, current_line_num + p_context_lines);
47+
context_snippet := array_to_string(lines[snippet_start_line_number:end_line_num], E'\n');
48+
49+
previous_context := CASE
50+
WHEN current_line_num > snippet_start_line_number
51+
THEN array_to_string(lines[snippet_start_line_number:current_line_num - 1], E'\n')
52+
ELSE ''
53+
END;
54+
line_offset_bytes := octet_length(previous_context);
55+
IF current_line_num > snippet_start_line_number THEN
56+
line_offset_bytes := line_offset_bytes + 1;
57+
END IF;
58+
59+
match_spans := '[]'::jsonb;
60+
search_start := 1;
61+
62+
LOOP
63+
match_start_char := regexp_instr(line_content, p_substring, search_start, 1, 0, flags);
64+
EXIT WHEN match_start_char = 0;
65+
66+
match_end_char := regexp_instr(line_content, p_substring, search_start, 1, 1, flags);
67+
IF match_end_char = 0 THEN
68+
match_end_char := char_length(line_content) + 1;
69+
END IF;
70+
71+
match_spans := match_spans || jsonb_build_array(
72+
jsonb_build_object(
73+
'start', line_offset_bytes + octet_length(left(line_content, match_start_char - 1)),
74+
'end', line_offset_bytes + octet_length(left(line_content, match_end_char - 1))
75+
)
76+
);
77+
78+
IF match_end_char <= match_start_char THEN
79+
search_start := match_start_char + 1;
80+
ELSE
81+
search_start := match_end_char;
82+
END IF;
83+
END LOOP;
84+
85+
RETURN NEXT;
86+
END IF;
87+
END LOOP;
88+
89+
RETURN;
90+
END;
91+
$$;

0 commit comments

Comments
 (0)