/* * Copyright Aduna (http://www.aduna-software.com/) (c) 2008. * * Licensed under the Aduna BSD-style license. */ package org.openrdf.sail.rdbms.evaluation; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.aduna.iteration.CloseableIteration; import org.openrdf.query.BindingSet; import org.openrdf.query.Dataset; import org.openrdf.query.QueryEvaluationException; import org.openrdf.query.algebra.TupleExpr; import org.openrdf.query.algebra.evaluation.QueryBindingSet; import org.openrdf.query.algebra.evaluation.impl.EvaluationStrategyImpl; import org.openrdf.sail.rdbms.RdbmsTripleRepository; import org.openrdf.sail.rdbms.RdbmsValueFactory; import org.openrdf.sail.rdbms.algebra.ColumnVar; import org.openrdf.sail.rdbms.algebra.SelectProjection; import org.openrdf.sail.rdbms.algebra.SelectQuery; import org.openrdf.sail.rdbms.algebra.SelectQuery.OrderElem; import org.openrdf.sail.rdbms.exceptions.RdbmsException; import org.openrdf.sail.rdbms.exceptions.RdbmsQueryEvaluationException; import org.openrdf.sail.rdbms.exceptions.UnsupportedRdbmsOperatorException; import org.openrdf.sail.rdbms.iteration.RdbmsBindingIteration; import org.openrdf.sail.rdbms.schema.IdSequence; /** * Extends the default strategy by accepting {@link SelectQuery} and evaluating * them on a database. * * @author James Leigh * */ public class RdbmsEvaluation extends EvaluationStrategyImpl { private Logger logger = LoggerFactory.getLogger(RdbmsEvaluation.class); private QueryBuilderFactory factory; private RdbmsValueFactory vf; private RdbmsTripleRepository triples; private IdSequence ids; public RdbmsEvaluation(QueryBuilderFactory factory, RdbmsTripleRepository triples, Dataset dataset, IdSequence ids) { super(new RdbmsTripleSource(triples), dataset); this.factory = factory; this.triples = triples; this.vf = triples.getValueFactory(); this.ids = ids; } @Override public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(TupleExpr expr, BindingSet bindings) throws QueryEvaluationException { if (expr instanceof SelectQuery) return evaluate((SelectQuery)expr, bindings); return super.evaluate(expr, bindings); } private CloseableIteration<BindingSet, QueryEvaluationException> evaluate(SelectQuery qb, BindingSet b) throws UnsupportedRdbmsOperatorException, RdbmsQueryEvaluationException { List<Object> parameters = new ArrayList<Object>(); try { QueryBindingSet bindings = new QueryBindingSet(b); String query = toQueryString(qb, bindings, parameters); try { Connection conn = triples.getConnection(); PreparedStatement stmt = conn.prepareStatement(query); int p = 0; for (Object o : parameters) { stmt.setObject(++p, o); } Collection<ColumnVar> proj = qb.getProjections(); RdbmsBindingIteration result = new RdbmsBindingIteration(stmt); result.setProjections(proj); result.setBindings(bindings); result.setValueFactory(vf); result.setIdSequence(ids); return result; } catch (SQLException e) { throw new RdbmsQueryEvaluationException(e.toString() + "\n" + query, e); } } catch (RdbmsException e) { throw new RdbmsQueryEvaluationException(e); } } private String toQueryString(SelectQuery qb, QueryBindingSet bindings, List<Object> parameters) throws RdbmsException, UnsupportedRdbmsOperatorException { QueryBuilder query = factory.createQueryBuilder(); if (qb.isDistinct()) { query.distinct(); } query.from(qb.getFrom()); for (ColumnVar var : qb.getVars()) { String name = qb.getBindingName(var); if (var.getValue() == null && bindings.hasBinding(name)) { query.filter(var, bindings.getValue(name)); } else if (var.getValue() != null && !bindings.hasBinding(name) && qb.getBindingNames().contains(name)) { bindings.addBinding(name, var.getValue()); } } int index = 0; for (SelectProjection proj : qb.getSqlSelectVar()) { ColumnVar var = proj.getVar(); String name = qb.getBindingName(var); if (!var.isHidden() && !bindings.hasBinding(name)) { var.setIndex(index); query.select(proj.getId()); query.select(proj.getStringValue()); index += 2; if (var.getTypes().isLiterals()) { query.select(proj.getLanguage()); query.select(proj.getDatatype()); index += 2; } } } for (OrderElem by : qb.getOrderElems()) { query.orderBy(by.sqlExpr, by.isAscending); if (qb.isDistinct()) { query.select(by.sqlExpr); } } if (qb.getLimit() != null) { query.limit(qb.getLimit()); } if (qb.getOffset() != null) { query.offset(qb.getOffset()); } parameters.addAll(query.getParameters()); if (logger.isDebugEnabled()) { logger.debug(query.toString()); logger.debug(parameters.toString()); } return query.toString(); } }