blob: 67562d7a2179b517e446f1c6921e2cbcbc3f1bf0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package arq;
import arq.cmdline.* ;
import jena.cmd.ArgDecl;
import jena.cmd.CmdException;
import jena.cmd.TerminationException;
import org.apache.jena.atlas.io.IndentedWriter ;
import org.apache.jena.atlas.lib.Lib ;
import org.apache.jena.atlas.logging.LogCtl ;
import org.apache.jena.query.* ;
import org.apache.jena.riot.RiotException ;
import org.apache.jena.riot.RiotNotFoundException ;
import org.apache.jena.riot.SysRIOT ;
import org.apache.jena.shared.JenaException ;
import org.apache.jena.shared.NotFoundException;
import org.apache.jena.sparql.ARQInternalErrorException ;
import org.apache.jena.sparql.core.Transactional ;
import org.apache.jena.sparql.core.TransactionalNull;
import org.apache.jena.sparql.mgt.Explain ;
import org.apache.jena.sparql.resultset.ResultSetException ;
import org.apache.jena.sparql.resultset.ResultsFormat ;
import org.apache.jena.sparql.util.QueryExecUtils ;
import org.apache.jena.system.Txn ;
public class query extends CmdARQ
{
private ArgDecl argRepeat = new ArgDecl(ArgDecl.HasValue, "repeat") ;
private ArgDecl argExplain = new ArgDecl(ArgDecl.NoValue, "explain") ;
private ArgDecl argOptimize = new ArgDecl(ArgDecl.HasValue, "opt", "optimize") ;
protected int repeatCount = 1 ;
protected int warmupCount = 0 ;
protected boolean queryOptimization = true ;
protected ModTime modTime = new ModTime() ;
protected ModQueryIn modQuery = null;
protected ModDataset modDataset = null ;
protected ModResultsOut modResults = new ModResultsOut() ;
protected ModEngine modEngine = new ModEngine() ;
public static void main (String... argv)
{
new query(argv).mainRun() ;
}
public query(String[] argv)
{
super(argv) ;
modQuery = new ModQueryIn(getDefaultSyntax()) ;
modDataset = setModDataset() ;
super.addModule(modQuery) ;
super.addModule(modResults) ;
super.addModule(modDataset) ;
super.addModule(modEngine) ;
super.addModule(modTime) ;
super.getUsage().startCategory("Control") ;
super.add(argExplain, "--explain", "Explain and log query execution") ;
super.add(argRepeat, "--repeat=N or N,M", "Do N times or N warmup and then M times (use for timing to overcome start up costs of Java)");
super.add(argOptimize, "--optimize=", "Turn the query optimizer on or off (default: on)") ;
}
/** Default syntax used when the syntax can not be determined from the command name or file extension
* The order of determination is:
* <ul>
* <li>Explicitly given --syntax</li>
* <li>File extension</li>
* <li>Command default</li>
* <li>System default</li>
* </ul>
*
*/
protected Syntax getDefaultSyntax() { return Syntax.defaultQuerySyntax ; }
@Override
protected void processModulesAndArgs()
{
super.processModulesAndArgs() ;
if ( contains(argRepeat) )
{
String[] x = getValue(argRepeat).split(",") ;
if ( x.length == 1 )
{
try { repeatCount = Integer.parseInt(x[0]) ; }
catch (NumberFormatException ex)
{ throw new CmdException("Can't parse "+x[0]+" in arg "+getValue(argRepeat)+" as an integer") ; }
}
else if ( x.length == 2 ) {
try { warmupCount = Integer.parseInt(x[0]) ; }
catch (NumberFormatException ex)
{ throw new CmdException("Can't parse "+x[0]+" in arg "+getValue(argRepeat)+" as an integer") ; }
try { repeatCount = Integer.parseInt(x[1]) ; }
catch (NumberFormatException ex)
{ throw new CmdException("Can't parse "+x[1]+" in arg "+getValue(argRepeat)+" as an integer") ; }
} else
throw new CmdException("Wrong format for repeat count: "+getValue(argRepeat)) ;
}
if ( isVerbose() )
ARQ.getContext().setTrue(ARQ.symLogExec) ;
if ( hasArg(argExplain) )
ARQ.setExecutionLogging(Explain.InfoLevel.ALL) ;
if ( hasArg(argOptimize) )
{
String x1 = getValue(argOptimize) ;
if ( hasValueOfTrue(argOptimize) || x1.equalsIgnoreCase("on") || x1.equalsIgnoreCase("yes") )
queryOptimization = true ;
else if ( hasValueOfFalse(argOptimize) || x1.equalsIgnoreCase("off") || x1.equalsIgnoreCase("no") )
queryOptimization = false ;
else throw new CmdException("Optimization flag must be true/false/on/off/yes/no. Found: "+getValue(argOptimize)) ;
}
}
protected ModDataset setModDataset()
{
return new ModDatasetGeneralAssembler() ;
}
@Override
protected void exec()
{
if ( ! queryOptimization )
ARQ.getContext().setFalse(ARQ.optimization) ;
if ( cmdStrictMode )
ARQ.getContext().setFalse(ARQ.optimization) ;
// Warm up.
for ( int i = 0 ; i < warmupCount ; i++ )
{
queryExec(false, ResultsFormat.FMT_NONE) ;
}
for ( int i = 0 ; i < repeatCount ; i++ )
queryExec(modTime.timingEnabled(), modResults.getResultsFormat()) ;
if ( modTime.timingEnabled() && repeatCount > 1 )
{
long avg = totalTime/repeatCount ;
String avgStr = modTime.timeStr(avg) ;
System.err.println("Total time: "+modTime.timeStr(totalTime)+" sec for repeat count of "+repeatCount+ " : average: "+avgStr) ;
}
}
@Override
protected String getCommandName() { return Lib.className(this) ; }
@Override
protected String getSummary() { return getCommandName()+" --data=<file> --query=<query>" ; }
/** Choose the dataset.
* <li> use the data as described on the command line
* <li> else use FROM/FROM NAMED if present (pass null to ARQ)
* <li> else provided an empty dataset and hope the query has VALUES/BIND
*/
protected Dataset getDataset(Query query) {
try {
Dataset ds = modDataset.getDataset();
if ( ds == null )
ds = dealWithNoDataset(query);
return ds;
}
catch (RiotNotFoundException ex) {
System.err.println("Failed to load data: " + ex.getMessage());
throw new TerminationException(1);
}
catch (RiotException ex) {
System.err.println("Failed to load data");
throw new TerminationException(1);
}
}
protected Query getQuery() {
try {
return modQuery.getQuery() ;
} catch (NotFoundException ex) {
System.err.println("Failed to load query: "+ex.getMessage());
throw new TerminationException(1);
}
}
// Policy for no command line dataset. null means "whatever" (use FROM)
protected Dataset dealWithNoDataset(Query query) {
if ( query.hasDatasetDescription() )
return null;
return DatasetFactory.createTxnMem();
//throw new CmdException("No dataset provided") ;
}
protected long totalTime = 0 ;
protected void queryExec(boolean timed, ResultsFormat fmt)
{
try {
Query query = getQuery() ;
if ( isVerbose() ) {
IndentedWriter out = new IndentedWriter(System.err, true);
query.serialize(out);
out.setLineNumbers(false);
out.println();
out.flush();
}
if ( isQuiet() )
LogCtl.setError(SysRIOT.riotLoggerName) ;
Dataset dataset = getDataset(query) ;
// Check there is a dataset. See dealWithNoDataset(query).
// The default policy is to create an empty one - convenience for VALUES and BIND providing the data.
if ( dataset == null && !query.hasDatasetDescription() ) {
System.err.println("Dataset not specified in query nor provided on command line.");
throw new TerminationException(1);
}
Transactional transactional = (dataset != null && dataset.supportsTransactions()) ? dataset : new TransactionalNull() ;
Txn.executeRead(transactional, ()->{
modTime.startTimer() ;
try ( QueryExecution qe = QueryExecutionFactory.create(query, dataset) ) {
try { QueryExecUtils.executeQuery(query, qe, fmt); }
catch (QueryCancelledException ex) {
System.out.flush();
System.err.println("Query timed out");
}
long time = modTime.endTimer();
if ( timed ) {
totalTime += time;
System.err.println("Time: " + modTime.timeStr(time) + " sec");
}
}
catch (ResultSetException ex) {
System.err.println(ex.getMessage());
ex.printStackTrace(System.err);
}
catch (QueryException qEx) {
// System.err.println(qEx.getMessage()) ;
throw new CmdException("Query Exeception", qEx);
}
});
}
catch (ARQInternalErrorException intEx) {
System.err.println(intEx.getMessage()) ;
if ( intEx.getCause() != null )
{
System.err.println("Cause:") ;
intEx.getCause().printStackTrace(System.err) ;
System.err.println() ;
}
intEx.printStackTrace(System.err) ;
}
catch (JenaException | CmdException ex) { throw ex ; }
catch (Exception ex) {
throw new CmdException("Exception", ex) ;
}
}
}