/*******************************************************************************
* Copyright (c) 2004, 2007 IBM Corporation and Cambridge Semantics Incorporated.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* File: $Source: /cvsroot/slrp/boca/com.ibm.adtech.boca.model/src/com/ibm/adtech/boca/glitter/BocaServerBGPQuery.java,v $
* Created by: Lee Feigenbaum (<a href="mailto:feigenbl@us.ibm.com">feigenbl@us.ibm.com</a>)
* Created on: 10/27/06
* Revision: $Id: ServerBGPQuery.java 229 2007-08-07 15:22:00Z mroy $
*
* Contributors: IBM Corporation - initial API and implementation
* Cambridge Semantics Incorporated - Fork to Anzo
*******************************************************************************/
package org.openanzo.datasource.nodecentric.query;
import java.sql.Connection;
import java.util.Collection;
import java.util.List;
import org.openanzo.datasource.nodecentric.internal.NodeCentricOperationContext;
import org.openanzo.datasource.nodecentric.sql.GlitterRdbWrapper;
import org.openanzo.exceptions.AnzoException;
import org.openanzo.glitter.query.QueryInformation;
import org.openanzo.jdbc.container.CoreDBConfiguration;
import org.openanzo.jdbc.container.query.AnzoBGPQuery;
import org.openanzo.jdbc.container.query.GraphSetType;
import org.openanzo.jdbc.layout.CompositeNodeLayout;
import org.openanzo.jdbc.query.NoSolutionsException;
import org.openanzo.jdbc.query.SQLQueryConstants;
import org.openanzo.jdbc.utils.ClosableIterator;
import org.openanzo.jdbc.utils.PreparedStatementProvider;
import org.openanzo.rdf.utils.Collections;
/**
* ServerBGPQuery creates SQL queries against the Anzo relational schema from conjoined triple patterns. The entire context of a single ServerBGPQuery instance
* can be constrained with a GRAPH clause (with either an IRI reference or a variable.)
*
* It does not handle UNION patterns or FILTERs.
*
* The algorithms in this class are based on research in:
* http://www.cs.wayne.edu/~artem/main/research/TR-DB-052006-CLJF.pdf#search=%22sparql%20sql%20optional%20wayne%22 adjusted to the particulars of the Anzo
* relational schema. Other deviations from Chebotko et al.'s work are documented below.
*
* @author lee
* @author Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com </a>)
*
*/
class ServerBGPQuery extends AnzoBGPQuery {
private final NodeCentricOperationContext context;
private final long numberDefaultGraphs;
private final int defaultGraphRevisioned;
private final int namedGraphsRevisioned;
private String defaultGraphStatementsTable = null;
private String namedGraphsStatementsTable = null;
private boolean bypassAcls = false;
private boolean datasetResolved = false;
private GraphSetType defaultGraphsType = null;
private GraphSetType namedGraphsType = null;
private static final boolean USE_EXISTS = false;
/**
* Create a new ServerBGPQuery
*
* @param context
* NodeCentric specific context, which contains connection to run queries against
* @param qi
* query
* @param lastTransactionTime
* If not null, all generated queries only find triples that were active as of the given time
*/
protected ServerBGPQuery(NodeCentricOperationContext context, QueryInformation qi, int revisionedDefaultGraph, int revisionedNamedGraphs, long validDefaultGraphs) {
super(qi);
this.numberDefaultGraphs = validDefaultGraphs;
this.context = context;
this.defaultGraphRevisioned = revisionedDefaultGraph;
this.namedGraphsRevisioned = revisionedNamedGraphs;
}
@Override
protected CoreDBConfiguration getConfiguration() {
return context.getConfiguration();
}
@Override
protected PreparedStatementProvider getPreparedStatementProvider() {
return context.getStatementProvider();
}
@Override
protected long getNumberOfValidDefaultGraphs() {
return numberDefaultGraphs;
}
@Override
protected Collection<Long> getValidDefaultGraphs() throws AnzoException {
ClosableIterator<Long> results = GlitterRdbWrapper.selectGraphs(this.context.getStatementProvider(), getConnection(), context.getConfiguration().getSessionPrefix(), SQLQueryConstants.defaultGraphsTempTable);
return Collections.toList(results);
}
@Override
protected Connection getConnection() {
return this.context.getConnection();
}
@Override
protected CompositeNodeLayout getNodeLayout() {
return this.context.getNodeLayout();
}
@Override
protected boolean bypassAcls() {
return bypassAcls;
}
@Override
protected GraphSetType getDefaultGraphsType() {
return defaultGraphsType;
}
@Override
protected GraphSetType getNamedGraphsType() {
return namedGraphsType;
}
@Override
protected String getNamedGraphInQuery(String columnName) {
if (USE_EXISTS) {
return "EXISTS (SELECT " + getDefaultGraphsTable() + ".ID FROM " + getDefaultGraphsTable() + " WHERE " + getDefaultGraphsTable() + ".ID=" + columnName + ")";
} else {
if (context.getConfiguration().getDriverClassName().equals("oracle.jdbc.OracleDriver")) {
return columnName + " IN(SELECT " + getQueryHint(getDefaultGraphsTable()) + " ID FROM " + getDefaultGraphsTable() + ")";
} else {
return super.getNamedGraphInQuery(columnName);
}
}
}
@Override
protected String getStatementTable() {
if (useDefaultDataset() && this.defaultGraphStatementsTable != null)
return this.defaultGraphStatementsTable;
else if (!useDefaultDataset() && this.namedGraphsStatementsTable != null)
return this.namedGraphsStatementsTable;
else
return ServerSQL.statementTable;
}
/**
* @param statementsTable
* the statementsTable to set
*/
public void setDefaultGraphStatementsTable(String statementsTable) {
this.defaultGraphStatementsTable = statementsTable;
}
/**
* @param statementsTable
* the statementsTable to set
*/
public void setNamedGraphsStatementsTable(String statementsTable) {
this.namedGraphsStatementsTable = statementsTable;
}
@Override
protected String getDefaultGraphsTable() {
return context.getConfiguration().getSessionPrefix() + ServerSQL.defaultGraphsTempTable;
}
@Override
protected String getNamedGraphsTable() {
return context.getConfiguration().getSessionPrefix() + ServerSQL.namedGraphsTempTable;
}
@Override
protected String getLiteralTable() {
return "ALL_LITERALS_VIEW";
}
protected void setDefaultGraphsType(GraphSetType type) {
this.defaultGraphsType = type;
}
protected void setNamedGraphsType(GraphSetType type) {
this.namedGraphsType = type;
}
/**
* @param bypassAcls
* the bypassAcls to set
*/
public void setBypassAcls(boolean bypassAcls) {
this.bypassAcls = bypassAcls;
}
/**
* @return the datasetResolved
*/
public boolean isDatasetResolved() {
return datasetResolved;
}
/**
* @param datasetResolved
* the datasetResolved to set
*/
public void setDatasetResolved(boolean datasetResolved) {
this.datasetResolved = datasetResolved;
}
@Override
protected List<String> populateConstraintsFromTriples(List<String> constraints, Iterable<TripleInstance> triples, String alternativeColumnForNamedGraphs) throws NoSolutionsException {
List<String> columns = super.populateConstraintsFromTriples(constraints, triples, alternativeColumnForNamedGraphs);
for (TripleInstance ti : triples) {
constraints.add(ti.getTripleTableAlias() + ".COMMITTED = 0 ");
if ((useDefaultDataset() && this.defaultGraphRevisioned == 1) || (!useDefaultDataset() && this.namedGraphsRevisioned == 1)) {
constraints.add(ti.getTripleTableAlias() + ".REND IS NULL ");
}
}
return columns;
}
@Override
protected String getQueryHint(String tableName) {
//if (tableName != null && context.getConfiguration().getDriverClassName().equals("oracle.jdbc.OracleDriver")) {
// return "/*+ cardinality (" + tableName + " 8) */";
// } else {
return "";
// }
}
}