|
Java форум JavaTalks форум программистов
|
|
|
|
| Предыдущая тема :: Следующая тема |
| Автор |
Сообщение |
ALeksandriys : 22 Новичок
|
Окт 13, 2006 21:20 |
|
|
Всем доброго..., помогите плиз, мне нужно сделать програму парсинга строк в файле, строки это запросы. Мне надо сделать анализ на тип запроса, тоесть разделить, 4-е типа, по типам запроса, потом каждый тип разделить по использованию общих таблиц, полей, условий выборки, группировки и т.д. И в конце, я должен буду получить получить четыре типа запросов с максимально большим количеством общих аргументов, Заранее спасибо.
Например
10 Select использующих таблицу T1, одно и тоже поле Р1 из таблицы T1 и т.д
и так все 4-е типа.
Дайте плиз хотя бы наводку бо я совсем пока незнаю как к этому подойти |
|
|
|
 |
Vlad : 1670 JavaTalks Team Member Откуда: ODS-KRK-LON-HFE
|
Окт 14, 2006 19:40 |
|
|
Не понятно какие 4 типа запросов имеються ввиду.
А для парсинга удобно использовать regex (regular expressions). В Java эту функциональость реализуют классы java.util.regex.Pattern и java.util.regex.Matcher.
Для хранения информации о запросе можно реализовать примерно такой класс:
| Код: |
class QueryMetaData {
public QueryMetaData(String query) {
// Parsing SQL SELECT expression (for example, by regex) ...
}
public int getColumnCount() { ... }
public String getColumnName(int index) { ... }
public int getTableCount() { ... }
public String getTableName(int index) { ... }
public String getTableAlias(int index) { ... }
public Collection<String> getTableColumns(int index) { ... }
public boolean hasColumn(String tblName, String colName) { ... }
public String getWhereClause() { ... }
}
|
Дальше собираем статистику с инстанций QueryMetaData.
Другой вариант: парсить и сразу собирать статистику, не сохраняя резутьтаты парсинга запроса.
| Код: |
public class QueryInfoCollector {
public parseQuery(String query) { ... }
// ...
private Map<String, Integer> tablesStat; // Entry = [tableName, occurences]
private Map<String, Integer> colmnsStat; // Entry = [tableName.columnName, occurences]
// ...
} |
---
Пример выражения для парсинга запроса SELECT:
| Код: |
String input = "SELECT a.c1, a.c2 , b.c1, b.c2 FROM tableA a, tableB b WHERE a.c1 = b.c2";
String emptyRegex = "[\\s]*";
String selectRegex = emptyRegex + "SELECT[\\s]+(.+)[\\s]+FROM[\\s]+(.+)[\\s]+(WHERE[\\s]+(.+))?" + emptyRegex;
Pattern ptrn = Patterm.compile(selectRegex, Pattern.CASE_INSENSITIVE);
Matcher m = ptrn.matcher(input);
if (m.matches()) {
String columnsClause = m.group(1); // "a.c1, a.c2 , b.c1, b.c2"
String fromClause = m.group(2); // "tableA a, tableB b"
String whereClause = m.group(4); // "a.c1 = b.c2"
// Parse fromClause to get table names and aliases...
// Parse columnClause to get column definitions...
// Parse whereClause...
} else {
System.out.println("Invalid SELECT query");
}
|
Последний раз редактировалось: Vlad (Окт 14, 2006 20:01), всего редактировалось 1 раз |
|
|
|
 |
Vlad : 1670 JavaTalks Team Member Откуда: ODS-KRK-LON-HFE
|
Окт 14, 2006 19:55 |
|
|
| Vlad писал(а): |
| Не понятно какие 4 типа запросов имеються ввиду. |
Наверняка SELECT, INSERT, UPDATE и DELETE.
Тогда для каждого из типов запроса нужно создать своё регулярное выражение. |
|
|
|
 |
ALeksandriys : 22 Новичок
|
Окт 14, 2006 23:23 |
|
|
Спасибо за пример! А как сделать чтобы он эту строку читал из файла?
Да 4-е типа запросов это insert, update, delete, select. Мне надо парсить их с каждым разом приближаясь к группе запросов с наибольшим количеством одинаковых аргументов,
Скиньте плиз пример группировки запросов с общими аргументами.
Для остальных типов запросов пример меняеться я так понял только ключевые слова а алгоритм такой же? А как создать для каждого запроса свое регулярное выражение? Еще раз спсибо за помощь  |
|
|
|
 |
Vlad : 1670 JavaTalks Team Member Откуда: ODS-KRK-LON-HFE
|
Окт 15, 2006 21:09 |
|
|
| ALeksandriys писал(а): |
| А как сделать чтобы он эту строку читал из файла? |
| Код: |
try {
FileInputStream is = new FileInputStream(fileName);
Scanner scanner = new Scanner(is);
QueryInfoCollector collector = new QueryInfoCollector();
while(scanner.hasNextLine()) {
String query = scanner.getNextLine();
collector.parseQuery(query);
}
System.out.println("Tables usage statistics:");
//...
} finally {
if (scanner != null) scanner.close();
} |
| ALeksandriys писал(а): |
| Для остальных типов запросов пример меняеться я так понял только ключевые слова а алгоритм такой же? А как создать для каждого запроса свое регулярное выражение? |
Привожу пример того, как можно вытащить инфу о колонках и таблицах запроса (естественно с некоторыми ограничениями: e.g. нет поддержки JOIN и т.д.).
| Код: |
public class QueryInfoCollector {
public parseQuery(String query) throws QueryParseException {
if (query == null || query.length == 0) {
throw new QueryParseException("Query string is null or empty");
}
// Наивно определяем с каким типом запроса имеет дело
if (query.toUpperCase().indexOf("SELECT") > -1) {
parseSelect(query);
} else if (query.toUpperCase().indexOf("UPDATE") > -1) {
parseUpdate(query);
} else if (query.toUpperCase().indexOf("INSERT") > -1) {
parseInsert(query);
} else if (query.toUpperCase().indexOf("DELETE") > -1) {
parseDelete(query);
} else {
throw new QueryParseException("Unknown or unsupported SQL query: " + query);
}
}
public void parseSelect(String query) throws QueryParseException {
Matcher m = SELECT_PATTERN.matcher(query);
if (m.matches()) {
String columnsClause = m.group(1); // "a.c1, a.c2 , b.c1, b.c2"
Map<String, String> cols = parseColumnList(columnsClause);
String fromClause = m.group(2); // "tableA a, tableB b"
Map<String, String> tables = parseTableList(fromClause);
// Делаем, что надо с полученными таблицами и ячейками...
} else {
throw new QueryParseException("Invalid SELECT query: " + query);
}
}
public void parseUpdate(String query) throws QueryParseException {...}
public void parseDelete(String query) throws QueryParseException {...}
public void parseInsert(String query) throws QueryParseException {...}
public void reset() {
// Очищаем статистику...
}
/** Parses tables list (tables delimited by comma) and returns the Map of pairs (<table name>, <table alias>) */
private Map<String, String> parseTableList(String str) {
Map<String, String> result = new HashMap<String, String>();
StringTokenizer tokenizer = new StringTokenizer(str, ",");
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken().trim();
Matcher m = TABLE_PATTERN.matcher(token);
if (m.matches()) {
String tblName = m.group(1);
String tblAlias = m.group(4);
result.put(tblName, tblAlias);
} else {
throw new QueryParseException("Invalid table token in FROM clause: " + str);
}
}
return result;
}
/** Parses columns list (columns delimited by comma) and returns the Map of pairs (<table name or alias>, <column name>) */
private Map<String, String> parseColumnList(String str) {
Map<String, String> result = new HashMap<String, String>();
StringTokenizer tokenizer = new StringTokenizer(str, ",");
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken().trim();
Matcher m = COLUMN_PATTERN.matcher(token);
if (m.matches()) {
String table = m.group(1);
String column = m.group(2);
result.put(table, column);
} else {
throw new QueryParseException("Invalid table token in FROM clause: " + str);
}
}
return result;
}
//...
private static final String EMPTY_REGEX = "[\\s]*";
private static final String SPACE_REGEX = "[\\s]+";
private static final String WHERE_CLAUSE_REGEX = "(WHERE" + SPACE_REGEX + "(.+) )?";
private static final String SELECT_REGEX = EMPTY_REGEX +
"SELECT" + SPACE_REGEX + "(.+)" + SPACE_REGEX +
"FROM" + SPACE_REGEX + "(.+)" + SPACE_REGEX +
WHERE_CLAUSE_REGEX + SPACE_REGEX +
"ORDER BY" + SPACE_REGEX + "(.+)" + EMPTY_REGEX;
private static final String UPDATE_REGEX = EMPTY_REGEX +
"UPDATE" + SPACE_REGEX + "(.+)" + SPACE_REGEX +
"SET" + SPACE_REGEX + "(.+)" + SPACE_REGEX +
WHERE_CLAUSE_REGEX + EMPTY_REGEX;
private static final String INSERT_REGEX = EMPTY_REGEX +
"INSERT" + SPACE_REGEX + "INTO" + SPACE_REGEX + "(.+)" + SPACE_REGEX + "(\\(" + SPACE_REGEX + "(.+)" + SPACE_REGEX + "\\))?"
"VALUES" + SPACE_REGEX + "\\(" + SPACE_REGEX + "(.+)" + SPACE_REGEX + "\\)" + EMPTY_REGEX;
private static final String DELETE_REGEX = EMPTY_REGEX +
"DELETE" + SPACE_REGEX + "FROM" + SPACE_REGEX + "(.+)" + SPACE_REGEX +
WHERE_CLAUSE_REGEX + EMPTY_REGEX;
private static final String IDENTIFIER_REGEX = "([\\w]*)";
private static final String COLUMN_REGEX = IDENTIFIER_REGEX + "[\\.]" + IDENTIFIER_REGEX;
private static final String TABLE_REGEX = IDENTIFIER_REGEX + "(" + SPACE_REGEX + "(AS" + SPACE_REGEX + ")?" + IDENTIFIER_REGEX + ")?";
private static final Pattern SELECT_PATTERN = Pattern.compile(SELECT_REGEX, Pattern.CASE_INSENSITIVE);
private static final Pattern UPDATE_PATTERN = Pattern.compile(UPDATE_REGEX, Pattern.CASE_INSENSITIVE);
private static final Pattern INSERT_PATTERN = Pattern.compile(INSERT_REGEX, Pattern.CASE_INSENSITIVE);
private static final Pattern DELETE_PATTERN = Pattern.compile(DELETE_REGEX, Pattern.CASE_INSENSITIVE);
private static final Pattern COLUMN_PATTERN = Pattern.compile(COLUMN_REGEX, Pattern.CASE_INSENSITIVE);
private static final Pattern TABLE_PATTERN = Pattern.compile(TABLE_REGEX, Pattern.CASE_INSENSITIVE); |
| ALeksandriys писал(а): |
| Скиньте плиз пример группировки запросов с общими аргументами. |
Это называется кластерный анализ. Думаю для начала Вам надо самому что-то почитать по этой теме, подумать как реализовать алгоритм, и уже потом, если что-то не получиться, обратиться на форум с конкретными вопросами. |
|
|
|
 |
ALeksandriys : 22 Новичок
|
Окт 16, 2006 12:04 |
|
|
| Спасибо тебе большое за помощь!!!! Я разобрался с кластерным анализом, но есть вопрос, можно скинуть ссылочку на его реализацию на Ява, чтобы я мог хоть от чего нибудь отталкиваться, а то я пытался с нуля сделать у меня не выходит, я путаюсь в ветках. |
|
|
|
 |
ALeksandriys : 22 Новичок
|
Окт 20, 2006 21:26 |
|
|
| Подскажите плиз! Как получить инфу из запроса про условия выборки и сортировки? |
|
|
|
 |
gesser : 3589 JavaTalks Team Member
|
Окт 22, 2006 16:50 |
|
|
| ALeksandriys писал(а): |
| Подскажите плиз! Как получить инфу из запроса про условия выборки и сортировки? |
Вы говорите про SQL? |
|
|
|
 |
ALeksandriys : 22 Новичок
|
Окт 22, 2006 23:18 |
|
|
| gesser писал(а): |
| ALeksandriys писал(а): |
| Подскажите плиз! Как получить инфу из запроса про условия выборки и сортировки? |
Вы говорите про SQL? |
Да абсолютно точно! Я знаю как получать информацию о таблицах и колонках, а теперь мне надо как получать о информацию из раздела Where, Group by, Order by, т.е об условиях выборки, группировки и сортировки!  |
|
|
|
 |
ALeksandriys : 22 Новичок
|
Окт 23, 2006 17:09 |
|
|
Как реализовать проверку соотвествия запросов пороговому значению для определения этих запросов в кадидаты на шаблон, исходя из этого алгоритма?
Есть X запросов с одинаковым содержимым поля FROM
Есть порог K (K<1).
Есть множество условий, которые встречаются в этих запросов.
Можно посчитать количество Ni условия Ui из множества условий, которые встречаются в запросах Х
Если Ni > X*K, то условие Ui попадает в шаблон.
Как реализовать переменную например "H", в которой будет храниться количество кандидатов на шаблон! По окочанию каждого прхода цикла проверки значение этой переменной, при Ni = true, должно возрасти на единицу H++. Если это значение после прохода цикла заданное количество раз, допустим получиться больше 5-ти, то сообщить что шаблон строить целесообразно, иначе нецелесообразно. |
|
|
|
 |
pavlentus : 12 Новичок
|
Окт 24, 2006 18:40 |
|
|
| Думаю слету это не реально, страницы 2 кода точно |
|
|
|
 |
Vlad : 1670 JavaTalks Team Member Откуда: ODS-KRK-LON-HFE
|
Окт 25, 2006 0:41 |
|
|
| ALeksandriys писал(а): |
| Есть множество условий, которые встречаются в этих запросов. |
Думаю, для начала надо определить какие типы условий будут парситься и точнее какая информация из них важна, т.к. разнообразие выражения WHERE практически не имеет границ.
| ALeksandriys писал(а): |
| Как реализовать переменную например "H", в которой будет храниться количество кандидатов на шаблон! |
| Код: |
| private int _templateCandidateCount = 0; // количество кандидатов на шаблон :) |
| ALeksandriys писал(а): |
| По окочанию каждого прхода цикла проверки... |
| Код: |
_templateCandidateCount = 0;
for (int i=0; i < T /* "заданное количество раз" */; i++) {
// Calculate N
// ...
if (N > K*x) { // "Ni = true" :)
_templateCandidateCount++;
}
}
if (_templateCandidateCount > 5) {
System.out.println("шаблон строить целесообразно");
} else {
System.out.println("шаблон строить нецелесообразно");
}
|
Это то, что можно реализовать по приведенному тобой алгоритму.  |
|
|
|
 |
ALeksandriys : 22 Новичок
|
Окт 25, 2006 12:46 |
|
|
| Влад спасибо за помощь! Подскажи плиз, как получить инфу из запроса про условия выборки, сортировки и группировки, у них алгоритм такой же как с полями и таблицами? |
|
|
|
 |
Vlad : 1670 JavaTalks Team Member Откуда: ODS-KRK-LON-HFE
|
Окт 25, 2006 13:48 |
|
|
| ALeksandriys писал(а): |
| Влад спасибо за помощь! |
Eto ne obiazatel'no pisat' v kazhdom topike, tem bolee 4to "спасибо" v karman ne polozhysh
| ALeksandriys писал(а): |
| как получить инфу из запроса про условия выборки, сортировки и группировки, у них алгоритм такой же как с полями и таблицами? |
Analogi4nyj, no
| Vlad писал(а): |
| для начала надо определить какие типы условий будут парситься и точнее какая информация из них важна, т.к. разнообразие выражения WHERE практически не имеет границ. |
..., 4toby mozhno bylo sozdat' nuzhnye reguliarnye vyrazhenija (naprimer, tolko dlia vyrazhenija tipa: "WHERE (value|col_id)=(value|col_id) ((AND|OR) (value|col_id)=(value|col_id))*"). Tiazhelo realizovat', esli imeesh proizvolnoe WHERE vyrazhenie (s vlozhennymi uslovyjami, raznymi EXISTS, BEETWEEN, IN, podzaprosami v konce koncov) - v etom slu4ae leg4e opredelitsa kakayu infu iz etoj vsej ku4i nado vytaschit' i po kakim harakteristikam (naprimer, tol'ko nazwanija polej i tablic na osnove polu4ennych is razbora SELECT i FROM dannyh).
PS. 4to eto u tebia za proekt takoj strannyj - kakaya kone4naya cel? |
|
|
|
 |
ALeksandriys : 22 Новичок
|
Окт 25, 2006 21:44 |
|
|
Насчет спасибо, это пока все чем я могу показать свою благодарность за помощь! Это мой дипломный проект конечная цель этой программы получить шаблон согласно критериям отбора, шаблон - это совокупность запросов схожих по своей характеристике, их схожесть опеределяеться пороговым значением (или критерием попадания в шаблон), задеться переменная статистики значение которой увеличиваеться каждый раз когда запрос попадает в кандидаты на шаблон, в конце переменная статистики сравниваеться с константой количества кандидатов на шаблон (значение ее задаеться в начале программы) и в случае если положительный ответ, делаеться заключение о целесообразности создания шаблона - вот этот кусочек сравнения всех переменных мне и осталось реализовать.  |
|
|
|
 |
|
|
Страница 1 из 2 На страницу 1, 2 След. |
Список форумов
-> Другие технологии |
|
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах
|
|