2014-10-12 4 views
2

Так что в основном я использую Java, JRI (R для Java) и RJDBC (с помощью JRI), которые все работают довольно хорошо. Теперь я хочу сделать свою программу максимально надежной. Скажем, что строка SQL_command - это своего рода мусор и не действительно действительный SQL-оператор. В этом случае ...JRI - Как найти ошибки в R

re.eval("sql_data <- dbGetQuery(conn, \"" + SQL_command + "\")"); 

... должно пойти не так. Мое мышление выглядит так: если эта команда R не удалась, в R. будет какой-то выход. Если все верно, нет выхода. Но как я могу захватить этот возможный выход?

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

Заранее благодарен!

+0

Я не понимаю этого ... Какой захват? re.capture.output() не существует. Если вы имеете в виду внутри R ... Не помогло. Как использовать «last.warning»? "Кот (last.warning)"? –

+0

Хорошо, вот почему это комментарий, а не ответ. Просто предложение. –

ответ

2

Я предлагаю поймать (возможные) исключения из-за R-кода непосредственно в R. Поэтому, если я подозреваю, что команда может дать ошибку, я бы использовал функцию try в R. Что-то в этом направлении :

 REXP y = re.eval("sql_data <- try(dbGetQuery(conn, \"" + SQL_command + "\"),silent=TRUE)"); 
     REXP x = re.eval("class(sql_data)"); 
     if ((x.asString()).equals("try-error")) { 
      System.out.println(y.asString()); 
      // do something to catch the exception 
     } else { 
     // do normal stuff 
     } 

Таким образом, вы также можете отобразить ошибку R.

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

 import java.io.*; 
     import org.rosuda.JRI.*; 
     public class Prova { 
     public static void main(String[] args) { 
      String[] commands = {"a<-try(dbGetQuery(conn,'show tables'))","a<-try(dbGetQuery(conn,'SS'))"}; 
      Rengine re=new Rengine (new String [] {"--vanilla"}, false, null); 
      re.eval("require(RMySQL)"); 
      re.eval("conn<-dbConnect(MySQL(),user='xxx',password='xxx',dbname='xxx')"); 
      for (int i=0;i<2;i++) { 
      REXP y = re.eval(commands[i]); 
      REXP x = re.eval("class(a)"); 
      if ((x.asString()).equals("try-error")) { 
       System.out.println(y.asString()); 
      } else { 
       System.out.println(x.asString()); 
      } 
      } 
      re.end(); 
     } 
     } 

Выход:

data.frame 
    Error in mysqlExecStatement(conn, statement, ...) : 
    RS-DBI driver: (could not run statement: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SS' at line 1) 
+0

Я пробовал это, но это не сработало. Извлекая объект из команды re.eval(), он просто прекращает делать то, что он сделал, всякий раз, когда команда R в скобках терпит неудачу. Другими словами: \t \t REXP x = re.eval (SOME_WRONG_R_CODE); пропускает все. –

+0

Можете ли вы предоставить именно команду SQL_command, которую вы даете R? – nicola

+0

sql_data <- dbGetQuery (conn, "SS") –

0

Согласно the documentation for the org.rosuda.JRI.Rengine.eval(String) method, null будет возвращен, если что-то пошло не так. Этот метод не вызывает никакого типа Exception, поэтому он не предлагает какого-либо способа определить причину проблемы.

org.rosuda.REngine.parseAndEval(String) method делает бросить пару Exception типов, REngineException и REXPMismatchException, которые могли бы предложить больше объяснений отказа, но документация не ясно, почему именно и когда они будут выброшены.

Так может случиться так, что лучшее, что вы можете сделать, это проверить на возвращаемое значение null.

+0

У меня нет этого метода parseAndEval(). re.parseAndEval (String) не существует в соответствии с Eclipse. –

+0

Обратите внимание, что метод 'parseAndEval' находится в совершенно другом классе (с почти точно таким же именем) в другом пакете. Таким образом, ваш объект 're' не сможет вызвать этот метод. – Bobulous

Смежные вопросы