Регулярное выражение для соответствия строки не в скобках - PullRequest
0 голосов
/ 04 января 2019

Я изо всех сил пытался найти регулярное выражение, которое помогло бы мне сопоставить 3 разные строки, только если они не заключены в скобки, но до сих пор мне удавалось сопоставить его, только если оно находится рядом с скобками, и в этой конкретной ситуации оно меня не устраивает.

Чтобы уточнить, мне нужно сопоставить строки "HAVING", "ORDER BY" и "GROUP BY", которые не содержатся ни в одной скобке, независимо от того, содержит ли скобка больше, чем просто строка.

В этом случае:

Select *
from some_table
group by something;

Должно совпадать, но:

Select *
from(
   Select *
   from some_other_table
   group by something_else
)

или

Select this, and_this
from(
   Select *
   from some_other_table
   having some_condition
)

не должен.

Я не эксперт по Javascript Regex, поэтому любая помощь, которую вы мне могли бы оказать, будет принята с благодарностью.

1 Ответ

0 голосов
/ 06 января 2019

Я предполагаю, что вы хотите проверить, содержит ли данный запрос SQL HAVING, ORDER BY или GROUP BY на верхнем уровне (не в подзапросе).

Это усложняется тем фактом, что внутри строковых литералов ('...'), заключенных в кавычки идентификаторов ("...") и комментариев (-- ...) могут содержаться как слова, так и слова (*1008*).

В следующем коде я предполагаю, что это все, что может "пойти не так" (т. Е. Нет других конструкций с кавычками), и что никакие символы в кавычках не являются особыми (в частности, \ по-другому не обрабатывается).

Идея:

  • Удалить все цитируемые конструкции, такие как строковые литералы и комментарии.
  • Удалить все группы в скобках.
  • Проверьте оставшуюся строку для ваших ключевых слов.

И под «удалить» я подразумеваю «заменить на пробел», потому что в противном случае существует вероятность создания новых токенов там, где их раньше не было (например, hav(...)IN"asdf"g превратится в havINg, если части в скобках / кавычки были просто заменено ничем).

Реализация:

function contains_groupy_bits(sql) {
    sql = sql.replace(/'[^']*'|"[^"]*"|--[^\n]*/g, ' ');
    let tmp;
    while ((tmp = sql.replace(/\([^()]*\)/g, ' ')) !== sql) {
        sql = tmp;
    }
    return /\b(?:having|order\s+by|group\s+by)\b/i.test(sql);
}

const examples = [
    `Select *
    from some_table
    group by something;`,

    `Select *
    from(
       Select *
       from some_other_table
       group by something_else
    )`,

    `Select this, and_this
    from(
       Select *
       from some_other_table
       having some_condition
    )`,

    `select name, count(*) from things
    where mark = '('
    group by name -- )`,
];

for (const ex of examples) {
    console.log("'" + ex + "': " + contains_groupy_bits(ex));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...