blob: 0e01da0ab30cd95a0e4129b478b43bac67fed937 [file] [log] [blame]
// Copyright (C) 2022 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
enum EscapeFlag {
CaseInsensitive = 1,
MatchAny = 2,
}
function escape(s: string, flags?: number): string {
flags = flags === undefined ? 0 : flags;
// See https://www.sqlite.org/lang_expr.html#:~:text=A%20string%20constant
s = s.replaceAll("'", "''");
s = s.replaceAll('[', '[[]');
if (flags & EscapeFlag.CaseInsensitive) {
s = s.replace(/[a-zA-Z]/g, (m) => {
const lower = m.toLowerCase();
const upper = m.toUpperCase();
return `[${lower}${upper}]`;
});
}
s = s.replaceAll('?', '[?]');
s = s.replaceAll('*', '[*]');
if (flags & EscapeFlag.MatchAny) {
s = `*${s}*`;
}
s = `'${s}'`;
return s;
}
export function escapeQuery(s: string): string {
return escape(s);
}
export function escapeSearchQuery(s: string): string {
return escape(s, EscapeFlag.CaseInsensitive | EscapeFlag.MatchAny);
}
export function escapeGlob(s: string): string {
// For globs we are only preoccupied by mismatching single quotes.
s = s.replaceAll("'", "''");
return `'*${s}*'`;
}