Я работаю над проектом, в котором мы переносим огромное количество (более 12000) просмотров в Hadoop / Impala из Oracle. Я написал небольшую утилиту Java для извлечения DDL-представления из Oracle и хотел бы использовать ANTLR4 для обхода AST и генерации DDL-выражения, совместимого с Impala.
Большая часть работы относительно просто, включает только переписывание некоторых Oracle специфических c синтаксических причуд в стиле Impala. Однако я столкнулся с проблемой, когда я не уверен, что у меня есть лучший ответ: у нас есть ряд особых случаев, когда значения из поля даты извлекаются в нескольких вызовах вложенных функций. Например, следующее извлекает день из поля Date:
TO_NUMBER(TO_CHAR(d.R_DATE , 'DD' ))
У меня есть грамматика ANTLR4, объявленная для Oracle SQL, и, следовательно, я получаю обратный вызов посетителя, когда он достигает TO_NUMBER
и TO_CHAR
также, но я хотел бы иметь специальную обработку для этого особого случая.
Нет ли другого способа, кроме реализации метода-обработчика для внешней функции, а затем прибегнуть к ручному обходу вложенной структуры, чтобы увидеть
У меня есть что-то похожее в сгенерированном классе Visitor:
@Override
public String visitNumber_function(PlSqlParser.Number_functionContext ctx) {
// FIXME: seems to be dodgy code, can it be improved?
String functionName = ctx.name.getText();
if (functionName.equalsIgnoreCase("TO_NUMBER")) {
final int childCount = ctx.getChildCount();
if (childCount == 4) {
final int functionNameIndex = 0;
final int openRoundBracketIndex = 1;
final int encapsulatedValueIndex = 2;
final int closeRoundBracketIndex = 3;
ParseTree encapsulated = ctx.getChild(encapsulatedValueIndex);
if (encapsulated instanceof TerminalNode) {
throw new IllegalStateException("TerminalNode is found at: " + encapsulatedValueIndex);
}
String customDateConversionOrNullOnOtherType =
customDateConversionFromToNumberAndNestedToChar(encapsulated);
if (customDateConversionOrNullOnOtherType != null) {
// the child node contained our expected child element, so return the converted value
return customDateConversionOrNullOnOtherType;
}
// otherwise the child was something unexpected, signalled by null
// so simply fall-back to the default handler
}
}
// some other numeric function, default handling
return super.visitNumber_function(ctx);
}
private String customDateConversionFromToNumberAndNestedToChar(ParseTree parseTree) {
// ...
}