Skip to content

Commit

Permalink
Create PolyAlgRequest for executing PolyAlg via websocket
Browse files Browse the repository at this point in the history
  • Loading branch information
tobias-weber committed May 2, 2024
1 parent 646182b commit 246646b
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 0 deletions.
104 changes: 104 additions & 0 deletions webui/src/main/java/org/polypheny/db/webui/Crud.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@
import org.polypheny.db.algebra.constant.Kind;
import org.polypheny.db.algebra.core.Sort;
import org.polypheny.db.algebra.polyalg.PolyAlgRegistry;
import org.polypheny.db.algebra.polyalg.parser.PolyAlgParser;
import org.polypheny.db.algebra.polyalg.parser.PolyAlgToAlgConverter;
import org.polypheny.db.algebra.polyalg.parser.nodes.PolyAlgNode;
import org.polypheny.db.algebra.type.AlgDataType;
import org.polypheny.db.algebra.type.AlgDataTypeField;
import org.polypheny.db.catalog.Catalog;
Expand Down Expand Up @@ -151,11 +154,13 @@
import org.polypheny.db.partition.PartitionManager;
import org.polypheny.db.partition.PartitionManagerFactory;
import org.polypheny.db.partition.properties.PartitionProperty;
import org.polypheny.db.plan.AlgCluster;
import org.polypheny.db.plugins.PolyPluginManager;
import org.polypheny.db.plugins.PolyPluginManager.PluginStatus;
import org.polypheny.db.processing.ImplementationContext;
import org.polypheny.db.processing.ImplementationContext.ExecutedContext;
import org.polypheny.db.processing.QueryContext;
import org.polypheny.db.rex.RexBuilder;
import org.polypheny.db.security.SecurityManager;
import org.polypheny.db.transaction.Statement;
import org.polypheny.db.transaction.Transaction;
Expand Down Expand Up @@ -208,6 +213,7 @@
import org.polypheny.db.webui.models.requests.EditTableRequest;
import org.polypheny.db.webui.models.requests.PartitioningRequest;
import org.polypheny.db.webui.models.requests.PartitioningRequest.ModifyPartitionRequest;
import org.polypheny.db.webui.models.requests.PolyAlgRequest;
import org.polypheny.db.webui.models.requests.UIRequest;
import org.polypheny.db.webui.models.results.RelationalResult;
import org.polypheny.db.webui.models.results.RelationalResult.RelationalResultBuilder;
Expand Down Expand Up @@ -2382,6 +2388,104 @@ private TimeUnit getFreshnessType( String freshnessId ) {
}


/**
* Execute a logical plan represented as PolyAlgebra from the Web-Ui PolyPlan builder
*/
public Result<?,?> executePolyAlg( PolyAlgRequest polyAlgRequest, Session session ) {
Transaction transaction = getTransaction( true, true, this );
transaction.getQueryAnalyzer().setSession( session );

Statement statement = transaction.createStatement();
long executionTime = 0;
long temp = 0;

InformationManager queryAnalyzer = transaction.getQueryAnalyzer().observe( this );

AlgRoot root;
try {
temp = System.nanoTime();

Snapshot snapshot = statement.getTransaction().getSnapshot();
RexBuilder rexBuilder = new RexBuilder( statement.getTransaction().getTypeFactory() );
AlgCluster cluster = AlgCluster.create( statement.getQueryProcessor().getPlanner(), rexBuilder, null, snapshot );
PolyAlgToAlgConverter converter = new PolyAlgToAlgConverter( snapshot, cluster );

PolyAlgParser parser = PolyAlgParser.create( polyAlgRequest.polyAlg );
PolyAlgNode node = (PolyAlgNode) parser.parseQuery();
root = converter.convert( node );

} catch ( Exception e ) {
log.error( "Caught exception while building the plan builder tree", e );
return RelationalResult.builder().error( e.getMessage() ).build();
}

// TODO: create separate method to reduce duplicate code with executeAlg
// Prepare
PolyImplementation polyImplementation = statement.getQueryProcessor().prepareQuery( root, true );

List<List<PolyValue>> rows;
try {
ResultIterator iterator = polyImplementation.execute( statement, getPageSize() );
rows = iterator.getNextBatch();
iterator.close();
} catch ( Exception e ) {
log.error( "Caught exception while iterating the plan builder tree", e );
return RelationalResult.builder().error( e.getMessage() ).build();
}

UiColumnDefinition[] header = new UiColumnDefinition[polyImplementation.getTupleType().getFieldCount()];
int counter = 0;
for ( AlgDataTypeField col : polyImplementation.getTupleType().getFields() ) {
header[counter++] = UiColumnDefinition.builder()
.name( col.getName() )
.dataType( col.getType().getFullTypeString() )
.nullable( col.getType().isNullable() )
.precision( col.getType().getPrecision() ).build();
}

List<String[]> data = LanguageCrud.computeResultData( rows, List.of( header ), statement.getTransaction() );

try {
executionTime += System.nanoTime() - temp;
transaction.commit();
} catch ( TransactionException e ) {
log.error( "Caught exception while committing the plan builder tree", e );
try {
transaction.rollback();
} catch ( TransactionException transactionException ) {
log.error( "Exception while rollback", transactionException );
}
throw new GenericRuntimeException( e );
}
RelationalResult finalResult = RelationalResult.builder()
.header( header )
.data( data.toArray( new String[0][] ) )
.xid( transaction.getXid().toString() )
.query( "Execute logical query plan" )
.build();

if ( queryAnalyzer != null ) {
InformationPage p1 = new InformationPage( "Query analysis", "Analysis of the query." );
InformationGroup g1 = new InformationGroup( p1, "Execution time" );
InformationText text;
if ( executionTime < 1e4 ) {
text = new InformationText( g1, String.format( "Execution time: %d nanoseconds", executionTime ) );
} else {
long millis = TimeUnit.MILLISECONDS.convert( executionTime, TimeUnit.NANOSECONDS );
// format time: see: https://stackoverflow.com/questions/625433/how-to-convert-milliseconds-to-x-mins-x-seconds-in-java#answer-625444
DateFormat df = new SimpleDateFormat( "m 'min' s 'sec' S 'ms'" );
String durationText = df.format( new Date( millis ) );
text = new InformationText( g1, String.format( "Execution time: %s", durationText ) );
}
queryAnalyzer.addPage( p1 );
queryAnalyzer.addGroup( g1 );
queryAnalyzer.registerInformation( text );
}

return finalResult;
}


/**
* Execute a logical plan coming from the Web-Ui plan builder
*/
Expand Down
24 changes: 24 additions & 0 deletions webui/src/main/java/org/polypheny/db/webui/WebSocket.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.polypheny.db.webui.crud.LanguageCrud;
import org.polypheny.db.webui.models.requests.AlgRequest;
import org.polypheny.db.webui.models.requests.GraphRequest;
import org.polypheny.db.webui.models.requests.PolyAlgRequest;
import org.polypheny.db.webui.models.requests.QueryRequest;
import org.polypheny.db.webui.models.requests.RegisterRequest;
import org.polypheny.db.webui.models.requests.RequestModel;
Expand Down Expand Up @@ -141,6 +142,29 @@ public void onMessage( final WsMessageContext ctx ) {
}
ctx.send( results );
break;
case "PolyAlgRequest":
PolyAlgRequest polyAlgRequest = ctx.messageAsClass( PolyAlgRequest.class );
if ( polyAlgRequest.runQuery ) {
System.out.println("Running query " + polyAlgRequest.polyAlg);

Result<?, ?> result = null;
try {
result = crud.executePolyAlg( polyAlgRequest, ctx.session );
} catch ( Throwable t ) {
ctx.send( RelationalResult.builder().error( t.getMessage() ).build() );
return;
}

if ( result.xid != null ) {
xIds.add( result.xid );
}
ctx.send( result );

} else {
System.out.println("Building tree for query " + polyAlgRequest.polyAlg);
}
break;

case "RegisterRequest":
RegisterRequest registerRequest = ctx.messageAsClass( RegisterRequest.class );
crud.authCrud.register( registerRequest, ctx );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2019-2024 The Polypheny Project
*
* Licensed 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 org.polypheny.db.webui.models.requests;

import lombok.Value;

@Value
public class PolyAlgRequest {
public String type;
public String polyAlg;
public boolean runQuery; // false if the parsed tree should only be generated, but not executed

}

0 comments on commit 246646b

Please sign in to comment.