001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 2008.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.sail.rdbms.evaluation;
007:
008: import info.aduna.iteration.CloseableIteration;
009:
010: import java.sql.Connection;
011: import java.sql.PreparedStatement;
012: import java.sql.SQLException;
013: import java.util.ArrayList;
014: import java.util.Collection;
015: import java.util.List;
016:
017: import org.openrdf.query.BindingSet;
018: import org.openrdf.query.Dataset;
019: import org.openrdf.query.QueryEvaluationException;
020: import org.openrdf.query.algebra.TupleExpr;
021: import org.openrdf.query.algebra.evaluation.QueryBindingSet;
022: import org.openrdf.query.algebra.evaluation.impl.EvaluationStrategyImpl;
023: import org.openrdf.sail.rdbms.RdbmsTripleRepository;
024: import org.openrdf.sail.rdbms.RdbmsValueFactory;
025: import org.openrdf.sail.rdbms.algebra.ColumnVar;
026: import org.openrdf.sail.rdbms.algebra.SelectProjection;
027: import org.openrdf.sail.rdbms.algebra.SelectQuery;
028: import org.openrdf.sail.rdbms.algebra.SelectQuery.OrderElem;
029: import org.openrdf.sail.rdbms.exceptions.RdbmsException;
030: import org.openrdf.sail.rdbms.exceptions.RdbmsQueryEvaluationException;
031: import org.openrdf.sail.rdbms.exceptions.UnsupportedRdbmsOperatorException;
032: import org.openrdf.sail.rdbms.iteration.RdbmsBindingIteration;
033: import org.openrdf.sail.rdbms.schema.IdSequence;
034:
035: import org.slf4j.Logger;
036: import org.slf4j.LoggerFactory;
037:
038: /**
039: * Extends the default strategy by accepting {@link SelectQuery} and evaluating
040: * them on a database.
041: *
042: * @author James Leigh
043: *
044: */
045: public class RdbmsEvaluation extends EvaluationStrategyImpl {
046: private Logger logger = LoggerFactory
047: .getLogger(RdbmsEvaluation.class);
048: private QueryBuilderFactory factory;
049: private RdbmsValueFactory vf;
050: private RdbmsTripleRepository triples;
051: private IdSequence ids;
052:
053: public RdbmsEvaluation(QueryBuilderFactory factory,
054: RdbmsTripleRepository triples, Dataset dataset,
055: IdSequence ids) {
056: super (new RdbmsTripleSource(triples), dataset);
057: this .factory = factory;
058: this .triples = triples;
059: this .vf = triples.getValueFactory();
060: this .ids = ids;
061: }
062:
063: @Override
064: public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
065: TupleExpr expr, BindingSet bindings)
066: throws QueryEvaluationException {
067: if (expr instanceof SelectQuery)
068: return evaluate((SelectQuery) expr, bindings);
069: return super .evaluate(expr, bindings);
070: }
071:
072: private CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
073: SelectQuery qb, BindingSet b)
074: throws UnsupportedRdbmsOperatorException,
075: RdbmsQueryEvaluationException {
076: List<Object> parameters = new ArrayList<Object>();
077: try {
078: QueryBindingSet bindings = new QueryBindingSet(b);
079: String query = toQueryString(qb, bindings, parameters);
080: try {
081: Connection conn = triples.getConnection();
082: PreparedStatement stmt = conn.prepareStatement(query);
083: int p = 0;
084: for (Object o : parameters) {
085: stmt.setObject(++p, o);
086: }
087: Collection<ColumnVar> proj = qb.getProjections();
088: RdbmsBindingIteration result = new RdbmsBindingIteration(
089: stmt);
090: result.setProjections(proj);
091: result.setBindings(bindings);
092: result.setValueFactory(vf);
093: result.setIdSequence(ids);
094: return result;
095: } catch (SQLException e) {
096: throw new RdbmsQueryEvaluationException(e.toString()
097: + "\n" + query, e);
098: }
099: } catch (RdbmsException e) {
100: throw new RdbmsQueryEvaluationException(e);
101: }
102: }
103:
104: private String toQueryString(SelectQuery qb,
105: QueryBindingSet bindings, List<Object> parameters)
106: throws RdbmsException, UnsupportedRdbmsOperatorException {
107: QueryBuilder query = factory.createQueryBuilder();
108: if (qb.isDistinct()) {
109: query.distinct();
110: }
111: query.from(qb.getFrom());
112: for (ColumnVar var : qb.getVars()) {
113: String name = qb.getBindingName(var);
114: if (var.getValue() == null && bindings.hasBinding(name)) {
115: query.filter(var, bindings.getValue(name));
116: } else if (var.getValue() != null
117: && !bindings.hasBinding(name)
118: && qb.getBindingNames().contains(name)) {
119: bindings.addBinding(name, var.getValue());
120: }
121: }
122: int index = 0;
123: for (SelectProjection proj : qb.getSqlSelectVar()) {
124: ColumnVar var = proj.getVar();
125: String name = qb.getBindingName(var);
126: if (!var.isHidden() && !bindings.hasBinding(name)) {
127: var.setIndex(index);
128: query.select(proj.getId());
129: query.select(proj.getStringValue());
130: index += 2;
131: if (var.getTypes().isLiterals()) {
132: query.select(proj.getLanguage());
133: query.select(proj.getDatatype());
134: index += 2;
135: }
136: }
137: }
138: for (OrderElem by : qb.getOrderElems()) {
139: query.orderBy(by.sqlExpr, by.isAscending);
140: if (qb.isDistinct()) {
141: query.select(by.sqlExpr);
142: }
143: }
144: if (qb.getLimit() != null) {
145: query.limit(qb.getLimit());
146: }
147: if (qb.getOffset() != null) {
148: query.offset(qb.getOffset());
149: }
150: parameters.addAll(query.getParameters());
151: if (logger.isDebugEnabled()) {
152: logger.debug(query.toString());
153: logger.debug(parameters.toString());
154: }
155: return query.toString();
156: }
157: }
|