package org.genedb.db.adhoc; import org.apache.log4j.PropertyConfigurator; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.orm.hibernate3.SessionFactoryUtils; import org.springframework.transaction.annotation.Transactional; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.net.URL; import java.util.Arrays; import java.util.List; import javax.annotation.Resource; /** * Issue an ad hoc HQL query against the database. * * @author rh11 * */ public class Query { private static void initLog4J(boolean verbose) { URL url = Query.class.getResource( verbose ? "/log4j.query-verbose.properties" : "/log4j.query.properties"); if (url == null) { throw new RuntimeException("Could not find classpath resource /log4j.test.properties"); } System.out.printf("Configuring Log4J from '%s'\n", url); PropertyConfigurator.configure(url); } public static void main(String[] args) throws IOException { boolean commit = false; boolean verbose = false; for (String arg: args) { if (arg.equals("--commit")) { commit = true; } else if (arg.equals("--verbose")) { verbose = true; } else { throw new IllegalArgumentException("Unrecognised argument: " + arg); } } initLog4J(verbose); Reader stdin = new InputStreamReader(System.in); char[] buf = new char[4096]; StringBuilder queries = new StringBuilder(); int n; while (-1 < (n = stdin.read(buf))) { queries.append(buf, 0, n); } ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Adhoc.xml"); Query q = applicationContext.getBean("adhoc-query", Query.class); q.rollback = !commit; try { q.execute(queries.toString()); } catch (ForceRollback e) { System.out.println("ROLLBACK"); return; } System.out.println("COMMIT"); } @Resource(name="sessionFactory") private SessionFactory sessionFactory; private boolean rollback = true; public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } @Transactional(rollbackFor=ForceRollback.class) public void execute(String queries) throws ForceRollback { for (String query: queries.split(";\\s+")) { executeSingleQuery(query.trim()); } if (rollback) { throw new ForceRollback(); } } private void executeSingleQuery(String query) { if (query == null) { throw new NullPointerException("Supplied query is null"); } if (query.length() == 0) { return; } Session session = SessionFactoryUtils.getSession(sessionFactory, false); org.hibernate.Query q = session.createQuery(query); if (query.matches("(?is)delete\\b.*")) { executeDelete(q); } else { executeSelect(q); } } private void executeSelect(org.hibernate.Query q) { q.setMaxResults(50); List<?> results = q.list(); for (Object o: results) { String stringValue = stringValueOf(o); System.out.printf(" %s%n", stringValue); } System.out.printf("-- %n%d results%n", results.size()); } private void executeDelete(org.hibernate.Query q) { int numDeleted = q.executeUpdate(); System.out.printf("-- %d rows deleted%n", numDeleted); } /** * Get the string value of an object, stringifying it nicely * even if it's an array. * * @param o the object * @return the string value */ private String stringValueOf(Object o) { String stringValue = o.toString(); if (o instanceof Object[]) { stringValue = Arrays.toString((Object[]) o); } else if (o instanceof int[]) { stringValue = Arrays.toString((int[]) o); } else if (o instanceof long[]) { stringValue = Arrays.toString((long[]) o); } else if (o instanceof short[]) { stringValue = Arrays.toString((short[]) o); } else if (o instanceof byte[]) { stringValue = Arrays.toString((byte[]) o); } else if (o instanceof char[]) { stringValue = Arrays.toString((char[]) o); } return stringValue; } } class ForceRollback extends Exception { }