xref: /aosp_15_r20/external/perfetto/ui/src/trace_processor/query_utils.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1// Copyright (C) 2022 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15enum EscapeFlag {
16  CaseInsensitive = 1,
17  MatchAny = 2,
18}
19
20function escape(s: string, flags?: number): string {
21  flags = flags === undefined ? 0 : flags;
22  // See https://www.sqlite.org/lang_expr.html#:~:text=A%20string%20constant
23  s = s.replaceAll("'", "''");
24  s = s.replaceAll('[', '[[]');
25  if (flags & EscapeFlag.CaseInsensitive) {
26    s = s.replace(/[a-zA-Z]/g, (m) => {
27      const lower = m.toLowerCase();
28      const upper = m.toUpperCase();
29      return `[${lower}${upper}]`;
30    });
31  }
32  s = s.replaceAll('?', '[?]');
33  s = s.replaceAll('*', '[*]');
34  if (flags & EscapeFlag.MatchAny) {
35    s = `*${s}*`;
36  }
37  s = `'${s}'`;
38  return s;
39}
40
41export function escapeQuery(s: string): string {
42  return escape(s);
43}
44
45export function escapeSearchQuery(s: string): string {
46  return escape(s, EscapeFlag.CaseInsensitive | EscapeFlag.MatchAny);
47}
48
49export function escapeGlob(s: string): string {
50  // For globs we are only preoccupied by mismatching single quotes.
51  s = s.replaceAll("'", "''");
52  return `'*${s}*'`;
53}
54