Получение аргументов из запроса SQL - PullRequest
0 голосов
/ 06 января 2019

Я хочу получить все аргументы из запроса SQL. В этом случае запросы представляют собой простые строки в массиве. У меня много пар запросов в следующей форме:

SELECT * FROM my_table t WHERE (t.attr1 = ? AND t.attr2 = ?) OR t.attr3= ?

И его пара (которая содержит параметры, которые я хочу получить):

SELECT * FROM my_table t WHERE (t.attr1 = 3 AND t.attr2 = 'str') OR t.attr3= 4

Таким образом, вывод будет:

3, 'str' and 4.

Как я могу получить эти значения на основе этих пар?

Я пытался с регулярным выражением в Java, но это может быть сложно, потому что? может быть числом, строка и так далее. Строка может содержать другую? который является частью строки, например:

UPDATE my_table SET attr2 = ? WHERE attr5 = ?
UPDATE my_table SET attr2 = 'Is it true?' WHERE attr5 = 'What is it?'

Ответы [ 2 ]

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

Вы можете сделать это с помощью этого подхода, где вы заменяете каждые ? на (.*) в своем запросе, а затем создаете шаблон на его основе. Затем примените другую пару строк с действительными значениями, а затем распечатайте значения во всех группах, которые будут динамически созданы в соответствии с ?, присутствующим в строке запроса.

Вот код Java, делающий то же самое.

// This map stores your paired queries where key stores the placeholder query and value stores the query having actual parameters.
Map<String, String> pairMap = new HashMap<>();
pairMap.put("SELECT * FROM my_table t WHERE (t.attr1 = ? AND t.attr2 = ?) OR t.attr3= ?", "SELECT * FROM my_table t WHERE (t.attr1 = 3 AND t.attr2 = 'str') OR t.attr3= 4");
pairMap.put("UPDATE my_table SET attr2 = ? WHERE attr5 = ?", "UPDATE my_table SET attr2 = 'Is it true?' WHERE attr5 = 'What is it?'");

pairMap.forEach((k,v) -> {
    System.out.println("For query: "+k);
    k = k.replaceAll("([*+^$()\\[\\]{}])", "\\\\$1"); // this escapes all the characters that have special meaning in regex so they get treated as literal characters
    k = k.replaceAll("\\?", "(.*)");

    Pattern p = Pattern.compile(k);
    Matcher m = p.matcher(v);
    if (m.matches()) {
        for (int i=0;i<m.groupCount();i++) {
            System.out.println(m.group(i+1));
        }
    } else {
        System.out.println("Didn't match");
    }
    System.out.println();
});

Какие отпечатки,

For query: SELECT * FROM my_table t WHERE (t.attr1 = ? AND t.attr2 = ?) OR t.attr3= ?
3
'str'
4

For query: UPDATE my_table SET attr2 = ? WHERE attr5 = ?
'Is it true?'
'What is it?'

Как вы можете видеть код, он работает для любых переменных значений заполнителей ? в строке запроса и печатает все значения, присутствующие в парном запросе, который имеет действительные значения.

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

Вот рабочий скрипт, который использует базовое сопоставление с регулярным выражением Java. Это работает, выполняя два матча. Сначала он просматривает каждый столбец / псевдоним, назначаемый позиционному заполнителю ?. Затем для каждого соответствующего столбца / псевдонима выполняется второй поиск строки запроса со связанными значениями.

String query1 = "SELECT * FROM my_table t WHERE (t.attr1 = ? AND t.attr2 = ?) OR t.attr3= ?";
String query2 = "SELECT * FROM my_table t WHERE (t.attr1 = 3 AND t.attr2 = 'str') OR t.attr3= 4";

String p1 = "([\\w.]+)\\s*=\\s*\\?(?=(([^']*'){2})*[^']*$)";
Pattern r1 = Pattern.compile(p1);
Matcher m1 = r1.matcher(query1);

// for each matching column/alias with a placeholder
while (m1.find()) {
    String p2 = m1.group(1) + "\\s*=\\s*([\\w.']+)";
    Pattern r2 = Pattern.compile(p2);
    Matcher m2 = r2.matcher(query2);

    // if we find it in the second query string, then print the value
    if (m2.find()) {
        System.out.println("Column: " + m1.group(1) + " has parameter value: " + m2.group(1));
    }
}

Column: t.attr1 has parameter value: 3
Column: t.attr2 has parameter value: 'str'
Column: t.attr3 has parameter value: 4

Обратите внимание, что здесь я делаю несколько предположений, в том числе то, что совпадающие столбцы будут содержать только символы слова (\w) плюс точка, а соответствующие значения будут включать только символы слова и одинарные кавычки (для строковых литералов). Вероятно, существует много крайних случаев, для которых вышеприведенный код не будет работать, также в зависимости от вашей базы данных и ее конкретного синтаксиса. Я предлагаю это немедленное решение проблемы, которую вы представили, и в качестве общего подхода, который можно было бы заставить работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...