package org.aksw.sparqlify.update; import java.sql.Connection; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.sql.DataSource; import org.aksw.commons.util.Pair; import org.apache.jena.graph.Node; import org.apache.jena.graph.NodeFactory; import org.apache.jena.sparql.core.Var; import org.apache.jena.sparql.engine.binding.Binding; import org.apache.jena.sparql.engine.binding.BindingHashMap; import org.apache.jena.sparql.engine.binding.BindingMap; import com.google.common.base.Joiner; public class ViewTable { private DataSource dataSource; private String tableName; private List<String> varNames; private boolean isCreated = false; private Connection conn; /** * Allow lazy creation of the table. * * @throws SQLException */ private void prepare() throws SQLException { if(!isCreated) { createTable(dataSource, tableName, varNames); isCreated = true; conn = dataSource.getConnection(); } } public static List<String> toStringSet(Set<Var> varNames) { List<String> result = new ArrayList<String>(); for(Var varName : varNames) { result.add(varName.getVarName()); } return result; } public ViewTable(DataSource dataSource, String tableName, Set<Var> varNames) { this.dataSource = dataSource; this.tableName = tableName; this.varNames = toStringSet(varNames); } public static Pair<List<String>, List<String>> getValues(Binding binding) { List<String> keys = new ArrayList<String>(); List<String> values = new ArrayList<String>(); Iterator<Var> it = binding.vars(); while(it.hasNext()) { Var key = it.next(); keys.add(key.getName()); values.add(binding.get(key).toString()); } return Pair.create(keys, values); } public static Pair<String, String> toParts(Binding binding) { Pair<List<String>, List<String>> pair = getValues(binding); return Pair.create( "(" + Joiner.on(", ").join(pair.getKey()) + ")", "('" + Joiner.on("', '").join(pair.getValue()) + "')"); } public static String toSqlPredicate(Binding binding) { Pair<String, String> pair = toParts(binding); return pair.getKey() + " = " + pair.getValue(); } private ResultSet executeQuery(String query) throws SQLException { // TODO Retry on connection error return conn.createStatement().executeQuery(query); } /** * * * Returns all bindings * * @param binding * @return * @throws SQLException */ public Iterable<Binding> lookup(Binding binding) throws SQLException { prepare(); String sql = "SELECT * FROM " + tableName + " WHERE TRUE AND " + toSqlPredicate(binding); ResultSet rs = executeQuery(sql); ResultSetMetaData meta = rs.getMetaData(); List<Binding> result = new ArrayList<Binding>(); while(rs.next()) { BindingMap item = new BindingHashMap(); for(int i = 1; i <= meta.getColumnCount(); ++i) { Object o = rs.getObject(i); // TODO HACK! Deal properly with the types here Node node = NodeFactory.createURI(o.toString()); item.add(Var.alloc(meta.getColumnName(i)), node); } } return result; } public void insert(Binding binding) throws SQLException { prepare(); Pair<String, String> pair = toParts(binding); String sql = "INSERT INTO " + tableName + pair.getKey() + " VALUES " + pair.getValue() + ";"; //" SET " + toSqlPredicate(binding) + ";"; //conn.createStatement().execute(sql); System.out.println(sql); } public void remove(Binding binding) throws SQLException { prepare(); String sql = "DELETE FROM " + tableName + " WHERE " + toSqlPredicate(binding) + ";"; conn.createStatement().execute(sql); } public void clear() throws SQLException { prepare(); String sql = "DELETE FROM " + tableName; conn.createStatement().execute(sql); } public void createIndex(String var) { // Create Index ... } public static void createTable(DataSource dataSource, String tableName, Iterable<String> varNames) throws SQLException { List<String> columns = new ArrayList<String>(); for(String varName : varNames) { columns.add("\t" + varName + " text"); } String sql = "CREATE TABLE " + tableName + "(\n" + Joiner.on(",\n").join(columns) + ");"; Connection conn = dataSource.getConnection(); try { conn.createStatement().execute(sql); } catch(Exception e) { // TODO HACK Check properly if table already exists System.err.println("Exception type: " + e.getClass()); e.printStackTrace(); } //conn.close(); } }