/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Created on Sep 15, 2011 */ package com.bigdata.rdf.sparql.ast; import java.util.Map; import org.openrdf.model.Value; import com.bigdata.bop.BOp; import com.bigdata.bop.BOpUtility; import com.bigdata.bop.IBindingSet; import com.bigdata.bop.PipelineOp; import com.bigdata.rdf.lexicon.BigdataValueCentricFullTextIndex; import com.bigdata.rdf.sail.sparql.ast.SimpleNode; import com.bigdata.rdf.sparql.ast.optimizers.IASTOptimizer; /** * A super container for the AST. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ */ public class ASTContainer extends ASTBase { /** * */ private static final long serialVersionUID = 1L; public interface Annotations extends QueryBase.Annotations { /** * The original query from which this AST was generated. */ String QUERY_STRING = "queryString"; /** * The parse tree generated from the query string (optional). For the * default integration, this is the parse tree assembled by the Sesame * <code>sparql.jjt</code> grammar. Other integrations may produce * different parse trees using different object models. * <p> * Note: There is no guarantee that the parse tree is a serializable * object. It may not need to be stripped off of the {@link QueryRoot} * if the {@link QueryRoot} is persisted or shipped to another node in a * cluster. */ String PARSE_TREE = "parseTree"; /** * The AST as received from the parser. This is either a * {@link QueryRoot} or an {@link UpdateRoot}. */ String ORIGINAL_AST = "originalAST"; /** * The AST as rewritten by the {@link IASTOptimizer}s. */ String OPTIMIZED_AST = "optimizedAST"; /** * The physical query plan (pipeline bops). */ String QUERY_PLAN = "queryPlan"; /** * The incoming binding set associated with the query plan, as * resulting from the query optimization phase. */ String OPTIMIZED_AST_BINDING_SETS = "optimizedASTBindingSets"; /** * The parsing time for the query (nanoseconds). */ String QUERY_PARSE_TIME = "queryParseTime"; /** * The time to batch resolve RDF {@link Value}s in the query to * {@link BigdataValue}s in the database (nanoseconds). */ String RESOLVE_VALUES_TIME = "resolveValuesTime"; /** * Flag which indicates completed resolution of IVs. * Used to prevent running resolution again on consequent calls to query.evaluate */ String RESOLVED = "resolved"; } /** * Deep copy constructor. */ public ASTContainer(final ASTContainer op) { super(op); } /** * Shallow copy constructor. */ public ASTContainer(final BOp[] args, final Map<String, Object> annotations) { super(args, annotations); } public ASTContainer(final QueryRoot queryRoot) { super(BOp.NOARGS, null/*anns*/); setOriginalAST(queryRoot); } public ASTContainer(final UpdateRoot updateRoot) { super(BOp.NOARGS, null/*anns*/); setOriginalUpdateAST(updateRoot); } /** * Return the original SPARQL QUERY -or- UPDATE from which this AST model was * generated. * * @return The original Query or Update -or- <code>null</code> if the AST * was not generated by the parser. */ public String getQueryString() { return (String) getProperty(Annotations.QUERY_STRING); } /** * Set the SPARQL QUERY -or- UPDATE string used to generate the AST model. * * @param queryString * The query string. */ public void setQueryString(final String queryString) { setProperty(Annotations.QUERY_STRING, queryString); } /** * Return the parse tree generated from the query string. */ public Object getParseTree() { return getProperty(Annotations.PARSE_TREE); } /** * Set the parse tree generated from the query string. * * @param parseTree * The parse tree (may be <code>null</code>). */ public void setParseTree(final Object parseTree) { setProperty(Annotations.PARSE_TREE, parseTree); } /** * Return <code>true</code> iff this {@link ASTContainer} models a SPARQL * UPDATE operation. */ public boolean isUpdate() { return getProperty(Annotations.ORIGINAL_AST) instanceof UpdateRoot; } /** * Return <code>true</code> iff this {@link ASTContainer} models a SPARQL * QUERY operation. */ public boolean isQuery() { return getProperty(Annotations.ORIGINAL_AST) instanceof QueryRoot; } /** * Return the original AST model (before any optimization). */ public UpdateRoot getOriginalUpdateAST() { return (UpdateRoot) getProperty(Annotations.ORIGINAL_AST); } /** * Set the original AST model (before any optimizations). */ public void setOriginalUpdateAST(final UpdateRoot updateRoot) { setProperty(Annotations.ORIGINAL_AST, updateRoot); } /** * Return the original AST model (before any optimization). */ public QueryRoot getOriginalAST() { return (QueryRoot) getProperty(Annotations.ORIGINAL_AST); } /** * Set the incoming binding sets associated with the optimized AST. */ public void setOptimizedASTBindingSets(final IBindingSet[] bindingSets) { setProperty(Annotations.OPTIMIZED_AST_BINDING_SETS, bindingSets); } /** * Return the incoming binding sets associated with the optimized AST. */ public IBindingSet[] getOptimizedASTBindingSets() { return (IBindingSet[]) getProperty(Annotations.OPTIMIZED_AST_BINDING_SETS); } /** * Set the original AST model (before any optimizations). */ public void setOriginalAST(final QueryRoot queryRoot) { setProperty(Annotations.ORIGINAL_AST, queryRoot); } /** * Return the optimized AST model. */ public QueryRoot getOptimizedAST() { return (QueryRoot) getProperty(Annotations.OPTIMIZED_AST); } /** * Set the query parse time in nanoseconds. */ public void setQueryParseTime(final Long parseTime) { setProperty(Annotations.QUERY_PARSE_TIME, parseTime); } /** * Get the query parse time in nanoseconds. */ public Long getQueryParseTime() { return (Long) getProperty(Annotations.QUERY_PARSE_TIME); } /** * Set the RDF value resolution time in nanoseconds. */ public void setResolveValuesTime(final Long nanos) { setProperty(Annotations.RESOLVE_VALUES_TIME, nanos); } /** * Get the resolve values time in nanoseconds. */ public Long getResolveValuesTime() { return (Long) getProperty(Annotations.RESOLVE_VALUES_TIME); } /** * Set the optimized AST model. * <p> * Note: You MUST deep copy the original AST to avoid destructive side * effects when the {@link IASTOptimizer}s are run. */ public void setOptimizedAST(final QueryRoot queryRoot) { setProperty(Annotations.OPTIMIZED_AST, queryRoot); } /** * Clears the optimized AST model (necessary when something on which it * depends has been changed in the original AST model, for example, if you * replace the {@link DatasetNode}). */ public void clearOptimizedAST() { clearProperty(Annotations.OPTIMIZED_AST); } /** * Return the physical query plan (pipeline bops). */ public PipelineOp getQueryPlan() { return (PipelineOp) getProperty(Annotations.QUERY_PLAN); } /** * Set the physical plan for query or update (pipeline bops). */ public void setQueryPlan(final PipelineOp queryPlan) { setProperty(Annotations.QUERY_PLAN, queryPlan); } public String toString() { final StringBuilder sb = new StringBuilder(); final String queryString = getQueryString(); final Object parseTree = getParseTree(); /* * Note: Resolve the original AST without regard to query versus update. */ final ASTBase originalAST = (ASTBase) getProperty(Annotations.ORIGINAL_AST); /* * Note: Resolve the optimized AST without regard to query versus * update. */ final ASTBase optimizedAST = (ASTBase) getProperty(Annotations.OPTIMIZED_AST); final PipelineOp queryPlan = getQueryPlan(); if (queryString != null) { sb.append("\n"); sb.append(Annotations.QUERY_STRING); sb.append("\n"); sb.append(queryString); sb.append("\n"); } if (parseTree != null) { sb.append("\n"); sb.append(Annotations.PARSE_TREE); sb.append("\n"); if(parseTree instanceof SimpleNode) { // Dump parse tree for sparql.jjt grammar. sb.append(((SimpleNode)parseTree).dump("")); } else { /* * Dump some other parse tree, assuming it implements toString() * as pretty print. */ sb.append(parseTree.toString()); sb.append("\n"); } } if (originalAST != null) { sb.append("\n"); sb.append(Annotations.ORIGINAL_AST); sb.append(originalAST); } if (optimizedAST != null) { sb.append("\n"); sb.append(Annotations.OPTIMIZED_AST); sb.append(optimizedAST); } if (queryPlan != null) { sb.append("\n"); sb.append(Annotations.QUERY_PLAN); sb.append("\n"); sb.append(BOpUtility.toString(queryPlan)); } return sb.toString(); } }