/*******************************************************************************
* 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/BocaServerSolutionGenerator.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: ServerSolutionGenerator.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.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import org.openanzo.analysis.RequestAnalysis;
import org.openanzo.cache.ICache;
import org.openanzo.datasource.nodecentric.internal.NodeCentricOperationContext;
import org.openanzo.datasource.nodecentric.operations.Contains;
import org.openanzo.datasource.nodecentric.query.predicates.TextLikePredicate;
import org.openanzo.datasource.nodecentric.sql.GlitterRdbWrapper;
import org.openanzo.datasource.nodecentric.sql.NamedGraphRdbWrapper;
import org.openanzo.exceptions.AnzoException;
import org.openanzo.exceptions.AnzoRuntimeException;
import org.openanzo.exceptions.ExceptionConstants;
import org.openanzo.exceptions.LogUtils;
import org.openanzo.glitter.exception.GlitterException;
import org.openanzo.glitter.exception.GlitterRuntimeException;
import org.openanzo.glitter.exception.UnknownGraphException;
import org.openanzo.glitter.query.FunctionalPredicate;
import org.openanzo.glitter.query.PatternSolution;
import org.openanzo.glitter.query.QueryController;
import org.openanzo.glitter.query.SolutionGenerator;
import org.openanzo.glitter.query.SolutionList;
import org.openanzo.glitter.query.SolutionSet;
import org.openanzo.glitter.query.SolutionUtils;
import org.openanzo.glitter.query.TextMatchPredicate;
import org.openanzo.glitter.query.TextMatchPredicate.TextMatchQuery;
import org.openanzo.glitter.query.planning.TripleNode;
import org.openanzo.glitter.query.rewriter.FunctionalPredicateRewriter;
import org.openanzo.glitter.syntax.abstrakt.BGP;
import org.openanzo.glitter.syntax.abstrakt.Expression;
import org.openanzo.glitter.syntax.abstrakt.Graph;
import org.openanzo.glitter.syntax.abstrakt.Subquery;
import org.openanzo.glitter.syntax.abstrakt.TreeNode;
import org.openanzo.glitter.syntax.abstrakt.TriplePatternNode;
import org.openanzo.glitter.syntax.abstrakt.Union;
import org.openanzo.glitter.util.Glitter;
import org.openanzo.jdbc.container.CoreDBConfiguration;
import org.openanzo.jdbc.container.query.AnzoBGPQuery;
import org.openanzo.jdbc.container.query.AnzoSolutionGeneratorBase;
import org.openanzo.jdbc.container.query.GraphSetType;
import org.openanzo.jdbc.container.sql.BaseSQL;
import org.openanzo.jdbc.layout.CompositeNodeLayout;
import org.openanzo.jdbc.query.IRdbValue;
import org.openanzo.jdbc.query.NoSolutionsException;
import org.openanzo.jdbc.query.NodeConverter;
import org.openanzo.jdbc.query.SQLQueryConstants;
import org.openanzo.jdbc.utils.PreparedStatementProvider;
import org.openanzo.jdbc.utils.RdbException;
import org.openanzo.ontologies.openanzo.NamedGraph;
import org.openanzo.rdf.Constants;
import org.openanzo.rdf.Statement;
import org.openanzo.rdf.TriplePattern;
import org.openanzo.rdf.URI;
import org.openanzo.rdf.Variable;
import org.openanzo.rdf.Constants.GRAPHS;
import org.openanzo.rdf.utils.UriGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* ServerSolutionGenerator implements the core of the Anzo backend for glitter queries; it translates SPARQL queries into SQL queries against the Anzo temporal
* RDF store schema.
*/
public class ServerSolutionGenerator extends AnzoSolutionGeneratorBase implements SolutionGenerator {
private static final Logger log = LoggerFactory.getLogger(ServerSolutionGenerator.class);
// myLock is true if we're the ones that started a transaction (and therefore must cleanup and commit
// at the end)
private boolean myLock = false;
private final boolean prepopulateSolutionNodes;
// an array of TreeNode's that the solution generator does not handle (if they're inside the current
// node)
@SuppressWarnings("unchecked")
// suppress conversion from covariant arrays to non-covariant generic types since it is a well known know Java generics limitation
final private Class<? extends TreeNode>[] notHandled = new Class[] { Graph.class, Union.class };
//NodeCentric Operation Context
private NodeCentricOperationContext context;
private String defaultGraphStatementsTable = null;
private String namedGraphsStatementsTable = null;
private int revisionedDefaultGraph = 0;
private int revisionedNamedGraphs = 0;
private String roleSql = null;
private GraphSetType defaultGraphsType = null;
private GraphSetType namedGraphsType = null;
private ICache<GraphSet, GraphSet> graphSets;
private static final String TEMP_COLUMNS = "TEMP_COLUMNS";
/**
* Create a new ServerSolutionGenerator
*
* @param context
* NodeCentric specific context, which contains connection to run queries against
* @param transactionTi
* this.graphSets = context.getDatasource().getGraphSets();me timestamp of last transaction to include in queries
*/
protected ServerSolutionGenerator(boolean prepopulateSolutionNodes) {
this.noDefaultGraphs = false;
this.noNamedGraphs = false;
this.prepopulateSolutionNodes = prepopulateSolutionNodes;
}
/**
* @param context
* the context to set
*/
public void setContext(NodeCentricOperationContext context) {
this.context = context;
this.graphSets = context.getDatasource().getGraphSets();
}
public String getQueryId() {
return (context != null) ? context.getOperationId() : null;
}
@Override
protected CoreDBConfiguration getConfiguration() {
return this.context.getConfiguration();
}
@Override
protected Logger getLogger() {
if (RequestAnalysis.isAnalysisEnabled()) {
return RequestAnalysis.getAnalysisLogger();
} else {
return log;
}
}
@Override
protected String getSessionPrefix() {
return this.context.getConfiguration().getSessionPrefix();
}
@Override
protected CompositeNodeLayout getNodeLayout() {
return this.context.getNodeLayout();
}
@Override
protected String getDefaultGraphsTempTable() {
return ServerSQL.defaultGraphsTempTable;
}
@Override
protected String getNamedGraphsTempTable() {
return ServerSQL.namedGraphsTempTable;
}
@Override
protected String getTemporaryTempTable() {
return ServerSQL.tempGraphsTempTable;
}
/**
* @return the context
*/
public NodeCentricOperationContext getContext() {
return this.context;
}
/**
* The ServerSolutionGenerator is initialized by ensuring that we're in a transaction and populating the temp tables with the valid URIs for the query
* dataset's default graph and named graphs
*/
@Override
public void initialize() throws GlitterException {
this.nodeConverter = new NodeConverter(this.context.getNodeLayout());
// start a transaction (if necessary), create a temp table with OK named graph IDs
Glitter.getLog().debug("Creating temporary graph tables and indexes");
this.myLock = !this.context.getDatasource().isInTransaction(this.context.getConnection());
if (this.myLock) {
try {
this.context.getDatasource().begin(this.context.getConnection(), false, false);
} catch (AnzoException ae) {
if (log.isDebugEnabled()) {
log.debug(LogUtils.RDB_MARKER, "Error initializing serversolutiongenerator", ae);
}
throw new GlitterException(ae.getErrorCode(), ae);
}
}
// long start = System.currentTimeMillis();
// System.err.println("Start:" + start);
super.initialize();
// System.err.println("Init:" + (System.currentTimeMillis() - start));
}
protected boolean datasetResolved() {
Boolean resolved = (Boolean) this.context.getAttribute("datasetResolved");
return resolved != null && resolved;
}
private boolean bypassAcls() {
Boolean bypass = (Boolean) this.context.getAttribute("bypassAcls");
return (bypass != null && bypass) || this.context.getOperationPrincipal().isSysadmin();
}
/**
* Empty the temp tables if we own them or configuration insists that we do; if we own the lock, commit the transaction.
*/
public void cleanup() throws GlitterException {
if (!this.myLock) {
try {
BaseSQL.truncateTableWithSessionMayCommit(this.context.getStatementProvider(), this.context.getConnection(), this.context.getConfiguration().getSessionPrefix(), SQLQueryConstants.defaultGraphsTempTable);
BaseSQL.truncateTableWithSessionMayCommit(this.context.getStatementProvider(), this.context.getConnection(), this.context.getConfiguration().getSessionPrefix(), SQLQueryConstants.namedGraphsTempTable);
BaseSQL.truncateTableWithSessionMayCommit(this.context.getStatementProvider(), this.context.getConnection(), this.context.getConfiguration().getSessionPrefix(), SQLQueryConstants.tempGraphsTempTable);
} catch (RdbException sqle) {
if (log.isDebugEnabled()) {
log.debug(LogUtils.RDB_MARKER, "Error clearing temporary tables", sqle);
}
}
}
if (this.myLock) {
try {
this.context.getDatasource().commit(this.context.getConnection(), false, false);
} catch (AnzoException ae) {
throw new GlitterException(ae.getErrorCode(), ae);
}
}
}
/**
*
* @param tempTable
* @param uri
* @return <tt>null</t> if the given <tt>uri</tt> is <tt>null</tt> or if the graph is not found or not in the dataset; <tt>0</tt> if the graph is a regular
* named graph in the dataset; <tt>1</tt> if the graph is a metadata graph in the dataset
* @throws SQLException
* @throws AnzoException
*/
private int getGraphTypeFromDatasetPart(String tempTable, URI uri) throws SQLException, AnzoException {
if (uri == null)
return -1;
Long id = this.context.getNodeLayout().fetchId(uri, this.context.getConnection());
if (id == null) {
return -1;
}
Integer result = GlitterRdbWrapper.containsRevisionedGraph(this.context.getStatementProvider(), this.context.getConnection(), id, this.context.getConfiguration().getSessionPrefix(), tempTable);
if (result == null || result.intValue() == 0) {
result = GlitterRdbWrapper.containsNonRevisionedGraph(this.context.getStatementProvider(), this.context.getConnection(), id, this.context.getConfiguration().getSessionPrefix(), tempTable);
if (result != null && result.intValue() > 0)
return 1;
} else {
return 0;
}
return -1;
}
public SolutionSet generateSolutions(TreeNode node, URI namedGraph, Variable namedGraphVariable, SolutionSet requiredBindings, QueryController controller) {
if (node instanceof BGP) {
BGP bgp = (BGP) node;
if (bgp.getFunctionalPredicate() instanceof TextMatchPredicate) {
String matchText = ((TextMatchPredicate) bgp.getFunctionalPredicate()).getTextMatch();
if (matchText.trim().length() > 0 && !matchText.equals("*")) {
return solveTextMatchBGP(namedGraph, namedGraphVariable, requiredBindings, bgp);
}
}
}
// we don't do anything which is a UNION
// or anything that is an ancestor of a node type that we don't handle (UNION, GRAPH)
if (node instanceof Subquery || node instanceof Graph || node instanceof Union || containsNodeType(node, this.notHandled)) {
return null;
}
// if this is a graph node, update our graph context and replace the node with the
/* GRAPH's graph pattern (we recurse this for the strange nested GRAPH cases)
while (node instanceof Graph) {
// If this is a graph, we process the graph variable or URI and
// continue with the child GraphPattern as our operative node.
TriplePatternComponent context = ((Graph) node).getGraphContext();
if (context instanceof Variable) {
namedGraphVariable = (Variable) context;
} else if (context instanceof URI) {
namedGraph = (URI) context;
} else {
throw new GlitterRuntimeException(ExceptionConstants.GLITTER.GRAPH_NOT_VAR, context.toString());
}
node = ((Graph) node).getGraphPattern();
}*/
// At this point, we know that node is not a GRAPH node and not a UNION node and contains
// neither.
// pull out some properties for the particular part of the dataset we're querying
boolean queryingDefaultGraph = namedGraphVariable == null && namedGraph == null;
String datasetTable = queryingDefaultGraph ? ServerSQL.defaultGraphsTempTable : ServerSQL.namedGraphsTempTable;
// If this is not a single triple pattern instance, we can only handle it if we can use temp tables
// and we are not dealing with any metadata graphs
if (!(node instanceof TriplePatternNode) && !this.context.getConfiguration().getSupportsTempOnFind()) {
return null;
}
try {
// If namedGraph != null, we need to know if it's in the appropriate part of the dataset and
// whether it is a regular named graph or a metadata graph
int namedGraphType = getGraphTypeFromDatasetPart(datasetTable, namedGraph);
boolean allMatch = namedGraph != null ? UriGenerator.isMetadataGraphUri(namedGraph) ? (queryingDefaultGraph ? includeAllMetadataGraphsInDefaultDataset : includeAllMetadataGraphsInNamedDataset) : (queryingDefaultGraph ? includeAllNamedGraphsInDefaultDataset : includeAllNamedGraphsInNamedDataset) : false;
// Short-circuit if:
// (1) we're querying the default graph which is empty (zero or unit solution)
// (2) we're querying the named graphs which are empty (zero or unit solution)
// (3) we're querying a specific named graph which is not in our dataset (zero or unit solution)
if ((queryingDefaultGraph && this.noDefaultGraphs) || (!queryingDefaultGraph && this.noNamedGraphs) || (namedGraph != null && !allMatch && namedGraphType == -1)) {
if (isNonVacuous(node))
throw new NoSolutionsException();
else
return unitSolution();
}
log.trace("generateSolutions - no metadata graphs or one specific named graph that is not a metadata graph");
AnzoBGPQuery query = getAnzoBGPQuery(node, namedGraph, namedGraphVariable, requiredBindings);
if (query instanceof ServerBGPQuery) {
ServerBGPQuery serverQuery = (ServerBGPQuery) query;
serverQuery.setDefaultGraphStatementsTable(this.defaultGraphStatementsTable);
serverQuery.setNamedGraphsStatementsTable(this.namedGraphsStatementsTable);
serverQuery.setBypassAcls(bypassAcls());
serverQuery.setDatasetResolved(datasetResolved());
serverQuery.setDefaultGraphsType(this.defaultGraphsType);
serverQuery.setNamedGraphsType(this.namedGraphsType);
}
SolutionSet solutions = getBindingsForQuery(query, node, null, controller);
if (solutions == null)
return null;
if (this.prepopulateSolutionNodes) {
for (PatternSolution solution : solutions) {
for (int i = 0; i < solution.size(); i++) {
populateRdbNode(solution.getBinding(i), this.context.getConnection());
populateRdbNode(solution.getValue(i), this.context.getConnection());
}
}
}
return solutions;
} catch (NoSolutionsException e) {
return new SolutionList();
} catch (SQLException e) {
log.error(LogUtils.RDB_MARKER, "Error generating solutions", e);
throw new GlitterRuntimeException(ExceptionConstants.GLITTER.SQL_EXCEPTION, e);
} catch (GlitterException e) {
if (e.getCause() != null)
throw new GlitterRuntimeException(ExceptionConstants.GLITTER.CANNOT_GENERATE_SOLUTIONS, e.getCause());
throw new GlitterRuntimeException(ExceptionConstants.GLITTER.CANNOT_GENERATE_SOLUTIONS, e);
} catch (AnzoException e) {
if (log.isDebugEnabled()) {
log.debug(LogUtils.RDB_MARKER, "Error generating solutions", e);
}
throw new GlitterRuntimeException(e);
}
}
private void populateRdbNode(Object node, Connection connection) throws RdbException {
if (node instanceof IRdbValue) {
IRdbValue value = (IRdbValue) node;
value.populate(connection);
}
}
/**
* Solves a BGP containing only a functional predicate and it's required triple pattern(s). This is the case for functional predicate BGP's created by the
* {@link FunctionalPredicateRewriter}.
*/
private SolutionSet solveTextMatchBGP(URI namedGraph, Variable namedGraphVariable, SolutionSet requiredBindings, BGP bgp) {
TextMatchPredicate match = (TextMatchPredicate) bgp.getFunctionalPredicate();
try {
// run the lucene query and build up the results, or return no solutions if the query has no matches.
//long start = System.currentTimeMillis();
TextMatchQuery luceneQuery = match.getLuceneQuery(namedGraph, namedGraphVariable);
if (luceneQuery == null) {
log.debug(LogUtils.RDB_MARKER, "solveTextMatchBGP returning no solutions because luceneQuery is null.");
return SolutionUtils.noSolutions();
}
log.debug(LogUtils.RDB_MARKER, "solveTextMatchBGP about to call executeIndexQueryInternal");
Collection<Statement> results = getContext().getDatasource().getIndexService().executeIndexQueryInternal(getContext(), luceneQuery, 0, -1);
if (!luceneQuery.graphs.isEmpty()) {
Collection<Statement> filteredResults = new HashSet<Statement>();
log.debug(LogUtils.RDB_MARKER, "solveTextMatchBGP filtering results based on luceneQuery.graphs.");
for (Statement stmt : results) {
if (luceneQuery.graphs.contains(stmt.getNamedGraphUri())) {
filteredResults.add(stmt);
}
}
log.debug(LogUtils.RDB_MARKER, "solveTextMatchBGP results size before filtering '{}'; after filtering '{}'", results.size(), filteredResults.size());
results = filteredResults;
} else {
log.debug(LogUtils.RDB_MARKER, "solveTextMatchBGP lucene query graphs is empty - results not being filtered.");
}
if (results.size() == 0) {
log.debug(LogUtils.RDB_MARKER, "solveTextMatchBGP returning no solutions because result size is zero.");
return SolutionUtils.noSolutions();
}
log.debug(LogUtils.RDB_MARKER, "solveTextMatchBGP returning results - size: {}", results.size());
return match.createSolutionSet(results, namedGraphVariable);
} catch (AnzoException e) {
throw new AnzoRuntimeException(e);
}
}
@Override
protected boolean handleBGP(AnzoBGPQuery query, TreeNode node) throws NoSolutionsException {
BGP bgp = (BGP) node;
TriplePattern ftp = null;
if (bgp.getFunctionalPredicate() != null) {
FunctionalPredicate fp = bgp.getFunctionalPredicate();
if (fp instanceof TextLikePredicate) {
query.addLikeMatch(((TextLikePredicate) fp).getVariable(), ((TextLikePredicate) fp).getTextQuery());
ftp = fp.getFunctionalTriplePattern();
} else if (fp instanceof TextMatchPredicate) {
String matchText = ((TextMatchPredicate) fp).getTextMatch();
if ((matchText.trim().length() == 0 || matchText.equals("*"))) {
query.addIsLiteral(((TextMatchPredicate) fp).getVar(), false);
} else {
return false;
}
ftp = fp.getFunctionalTriplePattern();
} else {
return false;
}
}
List<TriplePatternNode> nodes = new ArrayList<TriplePatternNode>();
for (TriplePatternNode tpn : bgp.getTriplePatterns()) {
if (ftp == null || !ftp.equals(tpn.getTriplePattern()))
nodes.add(tpn);
}
for (TripleNode noder : this.cqo.getOrderedSet(nodes.iterator())) {
if (noder.getUnMatchedVariableCount() > 0 && noder.getMatchedVariableCount() == 1) {
TriplePattern tp = noder.getTriple().getTriplePattern();
query.addExtraTriplePattern(tp.getSubject(), tp.getPredicate(), tp.getObject());
} else {
query.addTriplePattern(noder.getTriple().getTriplePattern());
}
}
return true;
}
@Override
protected AnzoBGPQuery createAnzoBGPQuery(TreeNode node) {
return new ServerBGPQuery(this.context, Glitter.getMostSpecificController(node, information), this.revisionedDefaultGraph, this.revisionedNamedGraphs, this.validGraphsInDefaultGraph);
}
@Override
protected Connection getConnection() {
return this.context.getConnection();
}
@Override
protected void clearTempTable() throws RdbException, SQLException {
BaseSQL.truncateTableWithSessionMayCommit(this.context.getStatementProvider(), this.context.getConnection(), this.context.getConfiguration().getSessionPrefix(), TEMP_COLUMNS);
for (int i = 0; i < 4; i++) {
BaseSQL.truncateTableWithSessionMayCommit(this.context.getStatementProvider(), this.context.getConnection(), this.context.getConfiguration().getSessionPrefix(), "TEMP_CONSTRAINT" + i);
}
}
@Override
protected PreparedStatementProvider getPreparedStatementProvider() {
return this.context.getStatementProvider();
}
public boolean sortedSolutions() {
return false;
}
public boolean canHandleSimultaneousRequests() {
return false;
}
public boolean canBindGraphVariables() {
return true;
}
public boolean usesRequiredBindings() {
return false;
}
// even though we do apply filters, we don't do it correctly for
// optional nodes TODO so we answer false here
public boolean willHandleFilters(Set<Expression> filters) {
return false;
}
@Override
protected void setGraphsType(boolean defaults, GraphSetType type) {
if (defaults) {
this.defaultGraphsType = type;
} else {
this.namedGraphsType = type;
}
}
@Override
protected int insertGraphByIdIfValid(Long graphId, String insertTable, boolean defaults) throws SQLException, GlitterException, AnzoException {
if (bypassAcls()) {
return GlitterRdbWrapper.insertGraphSysAdmin(this.context.getStatementProvider(), this.context.getConnection(), graphId, getSessionPrefix(), insertTable);
} else {
Long canBeReadPropId = this.context.getNodeLayout().fetchId(NamedGraph.canBeReadByProperty, this.context.getConnection());
return GlitterRdbWrapper.insertGraphIfValid(this.context.getStatementProvider(), this.context.getConnection(), getSessionPrefix(), insertTable, "ALL_STMTS_VIEW", this.roleSql, Long.toString(graphId), Long.toString(canBeReadPropId));
}
}
private GraphSet defaultGraphSet;
private GraphSet namedGraphSet;
private final static Random random = new Random();
@Override
protected boolean insertGraphsIfValid(Set<URI> graphs, String insertTable, boolean defaults) throws SQLException, GlitterException, AnzoException {
boolean isEnabled = RequestAnalysis.getAnalysisLogger().isDebugEnabled();
long start = 0;
if (isEnabled) {
start = System.currentTimeMillis();
}
try {
if (bypassAcls() || datasetResolved()) {
if (graphs.size() < 100 || graphs.size() > 25000) {
Map<URI, Long> graphIds = resolveSet(getNodeLayout(), getConnection(), graphs, true);
Contains.insertIdsToTempTable(this.context, insertTable, graphIds.values());
} else {
long startGs = 0;
if (isEnabled) {
startGs = System.currentTimeMillis();
}
GraphSet graphSet = new GraphSet(graphs);
GraphSet oldSet = graphSets.get(graphSet);
if (oldSet != null) {
GlitterRdbWrapper.insertGraphsFromQueryDataset(this.context.getStatementProvider(), this.context.getConnection(), oldSet.getSetId(), getSessionPrefix(), insertTable);
if (defaults) {
defaultGraphSet = oldSet;
} else {
namedGraphSet = oldSet;
}
if (isEnabled) {
RequestAnalysis.getAnalysisLogger().debug("[glitter_ServerSolutionGenerator_foundCachedGraphSet] {}", Long.toString(System.currentTimeMillis() - startGs));
}
return true;
}
if (isEnabled) {
RequestAnalysis.getAnalysisLogger().debug("[glitter_ServerSolutionGenerator_noCachedGraphSet] {}", Long.toString(System.currentTimeMillis() - startGs));
startGs = System.currentTimeMillis();
}
PreparedStatement ps = null;
try {
Map<URI, Long> graphIds = resolveSet(getNodeLayout(), getConnection(), graphs, true);
if (isEnabled) {
RequestAnalysis.getAnalysisLogger().debug("[glitter_ServerSolutionGenerator_resolveNodes] {}", Long.toString(System.currentTimeMillis() - startGs));
startGs = System.currentTimeMillis();
}
ps = context.getStatementProvider().getPreparedSQLStatement(GlitterRdbWrapper.insertQueryDataset, null, context.getConnection());
ps.clearBatch();
long dsId = random.nextLong();
graphSet.setSetId(dsId);
for (Long id : graphIds.values()) {
ps.setLong(1, id);
ps.setLong(2, dsId);
// ps.setString(3, context.getDatasource().getInstanceId());
ps.addBatch();
}
ps.executeBatch();
if (defaults) {
defaultGraphSet = graphSet;
} else {
namedGraphSet = graphSet;
}
graphSets.put(graphSet, graphSet);
GlitterRdbWrapper.insertGraphsFromQueryDataset(this.context.getStatementProvider(), this.context.getConnection(), graphSet.getSetId(), getSessionPrefix(), insertTable);
} catch (SQLException e) {
throw new AnzoException(ExceptionConstants.RDB.FAILED_EXECUTING_SQL, e);
} finally {
try {
if (ps != null)
ps.close();
} catch (SQLException sqle) {
if (log.isDebugEnabled()) {
log.error(LogUtils.RDB_MARKER, "Error closing prepared statement", sqle);
}
}
if (isEnabled) {
RequestAnalysis.getAnalysisLogger().debug("[glitter_ServerSolutionGenerator_cachedGraphSet] {}", Long.toString(System.currentTimeMillis() - startGs));
}
}
}
return true;
} else {
Map<URI, Long> graphIds = resolveSet(getNodeLayout(), getConnection(), graphs, false);
Long canBeReadPropId = this.context.getNodeLayout().fetchId(NamedGraph.canBeReadByProperty, this.context.getConnection());
for (Map.Entry<URI, Long> graphId : graphIds.entrySet()) {
int count = GlitterRdbWrapper.insertGraphIfValid(this.context.getStatementProvider(), this.context.getConnection(), getSessionPrefix(), insertTable, "ALL_STMTS_VIEW", this.roleSql, Long.toString(graphId.getValue()), Long.toString(canBeReadPropId));
if (count == 0)
throw new UnknownGraphException(graphId.getKey());
}
return true;
}
} finally {
if (isEnabled) {
RequestAnalysis.getAnalysisLogger().debug("[glitter_ServerSolutionGenerator_insertGraphsIsValid] {}:{}", Integer.toString(graphs.size()), Long.toString(System.currentTimeMillis() - start));
}
}
}
@Override
protected int insertAllGraphsIfValid(String insertTable, boolean defaults) throws SQLException, GlitterException, AnzoException {
if (bypassAcls()) {
if ((defaults && this.defaultGraphsType == GraphSetType.ALL_GRAPHS) || (!defaults && this.namedGraphsType == GraphSetType.ALL_GRAPHS)) {
return 1;
} else {
int total = GlitterRdbWrapper.insertAllNamedGraphs(this.context.getStatementProvider(), this.context.getConnection(), getSessionPrefix(), insertTable);
total += GlitterRdbWrapper.insertAllMetadataGraphs(this.context.getStatementProvider(), this.context.getConnection(), getSessionPrefix(), insertTable);
return total;
}
} else {
Long canBeReadPropId = this.context.getNodeLayout().fetchId(NamedGraph.canBeReadByProperty, this.context.getConnection());
Long ngDatasetId = this.context.getNodeLayout().fetchId(GRAPHS.GRAPHS_DATASET, this.context.getConnection());
Long ngDatasetMetadataId = this.context.getNodeLayout().fetchId(GRAPHS.GRAPHS_DATASET_META, this.context.getConnection());
Long mgDatasetId = this.context.getNodeLayout().fetchId(GRAPHS.METADATA_GRAPHS_DATASET, this.context.getConnection());
Long mgDatasetMetadataId = this.context.getNodeLayout().fetchId(GRAPHS.METADATA_GRAPHS_DATASET_META, this.context.getConnection());
return GlitterRdbWrapper.insertAllValidGraphs(this.context.getStatementProvider(), this.context.getConnection(), getSessionPrefix(), insertTable, "ALL_STMTS_VIEW", this.roleSql, Long.toString(canBeReadPropId), Long.toString(ngDatasetId), Long.toString(ngDatasetMetadataId), Long.toString(mgDatasetId), Long.toString(mgDatasetMetadataId));
}
}
@Override
protected int insertAllNamedGraphsIfValid(String insertTable, boolean defaults) throws SQLException, GlitterException, AnzoException {
if (bypassAcls()) {
if ((defaults && this.defaultGraphsType == GraphSetType.ALL_NAMED_GRAPHS) || (!defaults && this.namedGraphsType == GraphSetType.ALL_NAMED_GRAPHS)) {
return 10000;
} else {
int total = GlitterRdbWrapper.insertAllNamedGraphs(this.context.getStatementProvider(), this.context.getConnection(), getSessionPrefix(), insertTable);
return total;
}
} else {
Long canBeReadPropId = this.context.getNodeLayout().fetchId(NamedGraph.canBeReadByProperty, this.context.getConnection());
Long ngDatasetId = this.context.getNodeLayout().fetchId(GRAPHS.GRAPHS_DATASET, this.context.getConnection());
Long mgDatasetId = this.context.getNodeLayout().fetchId(GRAPHS.METADATA_GRAPHS_DATASET, this.context.getConnection());
return GlitterRdbWrapper.insertAllValidNamedGraphs(this.context.getStatementProvider(), this.context.getConnection(), getSessionPrefix(), insertTable, "ALL_STMTS_VIEW", this.roleSql, Long.toString(canBeReadPropId), Long.toString(ngDatasetId), Long.toString(mgDatasetId));
}
}
@Override
protected int insertAllMetadataGraphsIfValid(String insertTable, boolean defaults) throws SQLException, GlitterException, AnzoException {
if (bypassAcls()) {
if ((defaults && this.defaultGraphsType == GraphSetType.ALL_METADATA_GRAPHS) || (!defaults && this.namedGraphsType == GraphSetType.ALL_METADATA_GRAPHS)) {
return 1;
} else {
int total = GlitterRdbWrapper.insertAllMetadataGraphs(this.context.getStatementProvider(), this.context.getConnection(), getSessionPrefix(), insertTable);
return total;
}
} else {
Long canBeReadPropId = this.context.getNodeLayout().fetchId(NamedGraph.canBeReadByProperty, this.context.getConnection());
Long ngDatasetMetadataId = this.context.getNodeLayout().fetchId(GRAPHS.GRAPHS_DATASET_META, this.context.getConnection());
Long mgDatasetMetadataId = this.context.getNodeLayout().fetchId(GRAPHS.METADATA_GRAPHS_DATASET_META, this.context.getConnection());
return GlitterRdbWrapper.insertAllValidMetadataGraphs(this.context.getStatementProvider(), this.context.getConnection(), getSessionPrefix(), insertTable, "ALL_STMTS_VIEW", this.roleSql, Long.toString(canBeReadPropId), Long.toString(ngDatasetMetadataId), Long.toString(mgDatasetMetadataId));
}
}
@Override
protected int insertDatasetGraphsIfValid(Long datasetId, Long datasetGraphPropertyId, String insertTable, boolean defaults) throws SQLException, GlitterException, AnzoException {
if (bypassAcls()) {
return GlitterRdbWrapper.insertValidDatasetGraphsSysadmin(this.context.getStatementProvider(), this.context.getConnection(), datasetId, datasetId, datasetGraphPropertyId, getSessionPrefix(), insertTable, "ALL_STMTS_VIEW");
} else {
Long canBeReadPropId = this.context.getNodeLayout().fetchId(NamedGraph.canBeReadByProperty, this.context.getConnection());
return GlitterRdbWrapper.insertValidDatasetGraphs(this.context.getStatementProvider(), this.context.getConnection(), getSessionPrefix(), insertTable, "ALL_STMTS_VIEW", this.roleSql, Long.toString(datasetId), Long.toString(datasetId), Long.toString(datasetGraphPropertyId), Long.toString(canBeReadPropId));
}
}
@Override
protected long[] populateDatasetTables(CompositeNodeLayout layout, Connection connection, String defaultGraphsTempTable, String namedGraphsTempTable, Logger log) throws GlitterException {
boolean isEnabled = RequestAnalysis.getAnalysisLogger().isDebugEnabled();
long start = 0;
if (log.isDebugEnabled() || isEnabled) {
start = System.currentTimeMillis();
}
long[] ret = null;
try {
// cache role sql and transaction time sql
if (!bypassAcls()) {
Set<org.openanzo.rdf.URI> roles = (this.context.getOperationPrincipal() != null) ? this.context.getOperationPrincipal().getRoles() : Collections.singleton(Constants.DEFAULT_INTERNAL_USER);
if (roles.size() >= 100) { // probably not set anywhere
this.roleSql = "SELECT ID IN OBJECT_IDS_TEMP";
} else {
StringBuilder sb = new StringBuilder();
ArrayList<Long> validIds = new ArrayList<Long>();
for (Iterator<org.openanzo.rdf.URI> rolesIter = roles.iterator(); rolesIter.hasNext();) {
org.openanzo.rdf.URI roleURI = rolesIter.next();
Long id = this.context.getNodeLayout().fetchId(roleURI, this.context.getConnection());
if (id != null) {
validIds.add(id);
}
}
for (Iterator<Long> idsIterator = validIds.iterator(); idsIterator.hasNext();) {
sb.append(idsIterator.next());
if (idsIterator.hasNext()) {
sb.append(',');
}
}
this.roleSql = sb.toString();
}
}
ret = super.populateDatasetTables(layout, connection, defaultGraphsTempTable, namedGraphsTempTable, log);
if (isEnabled) {
RequestAnalysis.getAnalysisLogger().debug("[glitter_ServerSolutionGenerator_superPopulateDatabaseTables] {}", Long.toString(System.currentTimeMillis() - start));
}
this.defaultGraphStatementsTable = getStatementTable(getDefaultGraphsTempTable(), true, ret[0]);
this.revisionedDefaultGraph = (this.defaultGraphStatementsTable.equals(ServerSQL.nonRevisionedStatementTable)) ? -1 : this.defaultGraphStatementsTable.equals(ServerSQL.revisionedStatementTable) ? 1 : 0;
this.namedGraphsStatementsTable = getStatementTable(getNamedGraphsTempTable(), false, ret[1]);
this.revisionedNamedGraphs = (this.namedGraphsStatementsTable.equals(ServerSQL.nonRevisionedStatementTable)) ? -1 : this.namedGraphsStatementsTable.equals(ServerSQL.revisionedStatementTable) ? 1 : 0;
// System.err.println("[POPULATE DATASET TABLES] " + ret[0] + ":" + ret[1] + ":" + (System.currentTimeMillis() - start));
if (log.isDebugEnabled()) {
log.debug("[POPULATE DATASET TABLES] " + ret[0] + ":" + ret[1] + ":" + (System.currentTimeMillis() - start));
}
return ret;
} catch (SQLException e) {
log.error(LogUtils.RDB_MARKER, "Error populating dataset tables", e);
throw new GlitterRuntimeException(ExceptionConstants.GLITTER.ERROR_POPULATING_TABLES, e);
} catch (AnzoException e) {
if (log.isDebugEnabled()) {
log.debug(LogUtils.RDB_MARKER, "Error populating dataset tables", e);
}
throw new GlitterRuntimeException(e);
} finally {
if (isEnabled) {
RequestAnalysis.getAnalysisLogger().debug("[glitter_ServerSolutionGenerator_populateDatabaseTables] {}:{}:{}", new Object[] { Long.toString(System.currentTimeMillis() - start), (ret != null) ? ret[0] : 0, (ret != null) ? ret[1] : 0 });
}
}
}
private String getStatementTable(String datasetTable, boolean defaults, long totalGraphs) throws RdbException, SQLException {
boolean isEnabled = RequestAnalysis.getAnalysisLogger().isDebugEnabled();
long start = 0;
if (log.isDebugEnabled() || isEnabled) {
start = System.currentTimeMillis();
}
if (bypassAcls() && this.namedGraphsType != GraphSetType.LISTED) {
Long countRev = NamedGraphRdbWrapper.countAllRevisionedNamedGraphs(this.context.getStatementProvider(), this.context.getConnection());
if (countRev == 0)
return ServerSQL.nonRevisionedStatementTable;
else if (countRev == totalGraphs || NamedGraphRdbWrapper.countAllNonRevisionedNamedGraphs(this.context.getStatementProvider(), this.context.getConnection()) == 0)
return ServerSQL.revisionedStatementTable;
else
return ServerSQL.statementTable;
} else {
if (defaults && defaultGraphSet != null) {
if (defaultGraphSet.getNonRevisionedCount() == -1 && defaultGraphSet.getRevisionedCount() == -1) {
defaultGraphSet.setRevisionedCount(GlitterRdbWrapper.countValidRevisionedGraphsInSet(this.context.getStatementProvider(), this.context.getConnection(), defaultGraphSet.getSetId()));
if (isEnabled) {
RequestAnalysis.getAnalysisLogger().debug("[glitter_ServerSolutionGenerator_getStatementTableCountRevisioned] {}:{}", defaultGraphSet.getRevisionedCount(), Long.toString(System.currentTimeMillis() - start));
start = System.currentTimeMillis();
}
defaultGraphSet.setNonRevisionedCount((defaultGraphSet.getRevisionedCount() == totalGraphs) ? 0 : GlitterRdbWrapper.countValidNonRevisionedGraphsInSet(this.context.getStatementProvider(), this.context.getConnection(), defaultGraphSet.getSetId()));
if (isEnabled) {
RequestAnalysis.getAnalysisLogger().debug("[glitter_ServerSolutionGenerator_getStatementTableCountNonRevisioned] {}:{}", defaultGraphSet.getNonRevisionedCount(), Long.toString(System.currentTimeMillis() - start));
}
}
if (defaultGraphSet.getRevisionedCount() == 0) {
return ServerSQL.nonRevisionedStatementTable;
} else if (defaultGraphSet.getNonRevisionedCount() == 0) {
return ServerSQL.revisionedStatementTable;
} else {
return ServerSQL.statementTable;
}
} else if (!defaults && namedGraphSet != null) {
if (namedGraphSet.getNonRevisionedCount() == -1 && namedGraphSet.getRevisionedCount() == -1) {
namedGraphSet.setRevisionedCount(GlitterRdbWrapper.countValidRevisionedGraphsInSet(this.context.getStatementProvider(), this.context.getConnection(), namedGraphSet.getSetId()));
if (isEnabled) {
RequestAnalysis.getAnalysisLogger().debug("[glitter_ServerSolutionGenerator_getStatementTableCountRevisioned] {}:{}", namedGraphSet.getRevisionedCount(), Long.toString(System.currentTimeMillis() - start));
start = System.currentTimeMillis();
}
namedGraphSet.setNonRevisionedCount((namedGraphSet.getRevisionedCount() == totalGraphs) ? 0 : GlitterRdbWrapper.countValidNonRevisionedGraphsInSet(this.context.getStatementProvider(), this.context.getConnection(), namedGraphSet.getSetId()));
if (isEnabled) {
RequestAnalysis.getAnalysisLogger().debug("[glitter_ServerSolutionGenerator_getStatementTableCountNonRevisioned] {}:{}", namedGraphSet.getNonRevisionedCount(), Long.toString(System.currentTimeMillis() - start));
}
}
if (namedGraphSet.getRevisionedCount() == 0) {
return ServerSQL.nonRevisionedStatementTable;
} else if (namedGraphSet.getNonRevisionedCount() == 0) {
return ServerSQL.revisionedStatementTable;
} else {
return ServerSQL.statementTable;
}
} else {
long countNonRev = GlitterRdbWrapper.countValidNonRevisionedGraphs(this.context.getStatementProvider(), this.context.getConnection(), datasetTable, this.context.getConfiguration().getSessionPrefix());
if (countNonRev == 0) {
return ServerSQL.revisionedStatementTable;
} else {
Long countRev = GlitterRdbWrapper.countValidRevisionedGraphs(this.context.getStatementProvider(), this.context.getConnection(), datasetTable, this.context.getConfiguration().getSessionPrefix());
if (countRev == 0) {
return ServerSQL.nonRevisionedStatementTable;
} else {
return ServerSQL.statementTable;
}
}
}
}
}
}