diff --git a/src/main/java/org/polypheny/simpleclient/cli/GavelNGCommand.java b/src/main/java/org/polypheny/simpleclient/cli/GavelNGCommand.java new file mode 100644 index 00000000..65bfd590 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/cli/GavelNGCommand.java @@ -0,0 +1,124 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.cli; + + +import com.github.rvesse.airline.HelpOption; +import com.github.rvesse.airline.annotations.Arguments; +import com.github.rvesse.airline.annotations.Command; +import com.github.rvesse.airline.annotations.Option; +import com.google.api.client.util.store.DataStore; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import javax.inject.Inject; +import lombok.extern.slf4j.Slf4j; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.executor.Executor.ExecutorFactory; +import org.polypheny.simpleclient.executor.PolyphenyDbExecutor; +import org.polypheny.simpleclient.executor.PolyphenyDbJdbcExecutor.PolyphenyDbJdbcExecutorFactory; +import org.polypheny.simpleclient.executor.PolyphenyDbMongoQlExecutor.PolyphenyDbMongoQlExecutorFactory; +import org.polypheny.simpleclient.main.GavelNGScenario; + + +@Slf4j +@Command(name = "gavelng", description = "Mode for quick testing of Polypheny-DB using the Gavel benchmark.") +public class GavelNGCommand implements CliRunnable { + + @SuppressWarnings("SpringAutowiredFieldsWarningInspection") + @Inject + private HelpOption help; + + @Arguments(description = "Task { schema | data | workload | warmup } and multiplier and { view | materialized }.") + private List args; + + @Option(name = { "-pdb", "--polyphenydb" }, title = "IP or Hostname", arity = 1, description = "IP or Hostname of Polypheny-DB (default: 127.0.0.1).") + public static String polyphenyDbHost = "127.0.0.1"; + + @Option(name = { "--writeCSV" }, arity = 0, description = "Write a CSV file containing execution times for all executed queries (default: false).") + public boolean writeCsv = false; + + @Option(name = { "--queryList" }, arity = 0, description = "Dump all Gavel queries as SQL into a file (default: false).") + public boolean dumpQueryList = false; + + + @Override + public int run() { + if ( args == null || args.size() < 1 ) { + System.err.println( "Missing task" ); + System.exit( 1 ); + } + + List datastores = new ArrayList(){{ + add("hsqldb"); + add("mongodb"); + }}; + QueryMode queryMode = QueryMode.TABLE; + int multiplier = 1; + if ( args.size() > 1 ) { + multiplier = Integer.parseInt( args.get( 1 ) ); + if ( multiplier < 1 ) { + System.err.println( "Multiplier needs to be a integer > 0!" ); + System.exit( 1 ); + } + if ( args.size() > 2 ) { + datastores = Arrays.asList( args.get( 2 ).split( "," ) ); + } + } + + ExecutorFactory mqlExecutorFactory = new PolyphenyDbMongoQlExecutorFactory( polyphenyDbHost ); + ExecutorFactory jdbcExecutorFactory = new PolyphenyDbJdbcExecutorFactory( polyphenyDbHost, true ); + + try { + if ( args.get( 0 ).equalsIgnoreCase( "data" ) ) { + GavelNGScenario.data( jdbcExecutorFactory, mqlExecutorFactory, multiplier, true, queryMode ); + } else if ( args.get( 0 ).equalsIgnoreCase( "workload" ) ) { + GavelNGScenario.workload( jdbcExecutorFactory, mqlExecutorFactory, multiplier, true, writeCsv, dumpQueryList, queryMode ); + } else if ( args.get( 0 ).equalsIgnoreCase( "schema" ) ) { + PolyphenyDbExecutor.PolyphenyDbInstance.deployStores( true, jdbcExecutorFactory, datastores ); + GavelNGScenario.schema( jdbcExecutorFactory, mqlExecutorFactory, true, queryMode ); + } else if ( args.get( 0 ).equalsIgnoreCase( "warmup" ) ) { + GavelNGScenario.warmup( jdbcExecutorFactory, mqlExecutorFactory, multiplier, true, dumpQueryList, queryMode ); + } else { + System.err.println( "Unknown task: " + args.get( 0 ) ); + } + } catch ( Throwable t ) { + log.error( "Exception while executing Gavel!", t ); + System.exit( 1 ); + } + + try { + Thread.sleep( 2000 ); + } catch ( InterruptedException e ) { + throw new RuntimeException( "Unexpected interrupt", e ); + } + + return 0; + } + + +} diff --git a/src/main/java/org/polypheny/simpleclient/cli/Main.java b/src/main/java/org/polypheny/simpleclient/cli/Main.java index eef00029..ca4bfa30 100644 --- a/src/main/java/org/polypheny/simpleclient/cli/Main.java +++ b/src/main/java/org/polypheny/simpleclient/cli/Main.java @@ -52,6 +52,7 @@ public static void main( String[] args ) throws SQLException { builder.withCommands( YcsbCommand.class ); builder.withCommands( DumpCommand.class ); builder.withCommands( HelpCommand.class ); + builder.withCommands( GavelNGCommand.class ); builder.withDefaultCommand( HelpCommand.class ); CliRunnable cmd = builder.build().parse( args ); diff --git a/src/main/java/org/polypheny/simpleclient/executor/OltpBenchPolyphenyDbExecutor.java b/src/main/java/org/polypheny/simpleclient/executor/OltpBenchPolyphenyDbExecutor.java index baf5e58c..f9008565 100644 --- a/src/main/java/org/polypheny/simpleclient/executor/OltpBenchPolyphenyDbExecutor.java +++ b/src/main/java/org/polypheny/simpleclient/executor/OltpBenchPolyphenyDbExecutor.java @@ -94,11 +94,17 @@ public void dropStore( String name ) throws ExecutorException { @Override - public void deployStore( String name, String clazz, String config ) throws ExecutorException { + public void setPolicies( String clauseName, String value ) throws ExecutorException { + + } + + + @Override + public void deployStore( String name, String clazz, String config, String store ) throws ExecutorException { PolyphenyDbJdbcExecutor executor = null; try { executor = jdbcExecutorFactory.createExecutorInstance( null ); - executor.deployStore( name, clazz, config ); + executor.deployStore( name, clazz, config, store ); executor.executeCommit(); } catch ( ExecutorException e ) { throw new ExecutorException( "Error while executing query via JDBC", e ); diff --git a/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbCypherExecutor.java b/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbCypherExecutor.java index 1850e522..c68ffa5f 100644 --- a/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbCypherExecutor.java +++ b/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbCypherExecutor.java @@ -97,6 +97,12 @@ public void executeInsertList( List batchList, AbstractConfig c } + @Override + public void setPolicies( String clauseName, String value ) throws ExecutorException { + //NoOp + } + + public static class PolyphenyDbCypherExecutorFactory extends ExecutorFactory { private final String host; diff --git a/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbExecutor.java b/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbExecutor.java index 7b0d8b2c..7117acc2 100644 --- a/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbExecutor.java +++ b/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbExecutor.java @@ -51,12 +51,15 @@ public interface PolyphenyDbExecutor extends Executor { AtomicInteger nextPort = new AtomicInteger( 3300 ); List storeNames = new ArrayList<>(); - + Map> dataStoreNames = new HashMap<>(); + default Map> getDataStoreNames() { + return dataStoreNames; + } void dropStore( String name ) throws ExecutorException; - void deployStore( String name, String clazz, String config ) throws ExecutorException; + void deployStore( String name, String clazz, String config, String store ) throws ExecutorException; default String deployHsqldb() throws ExecutorException { @@ -64,12 +67,12 @@ default String deployHsqldb() throws ExecutorException { deployStore( storeName, "org.polypheny.db.adapter.jdbc.stores.HsqldbStore", - "{maxConnections:\"25\",trxControlMode:locks,trxIsolationLevel:read_committed,type:Memory,tableType:Memory,mode:embedded}" ); + "{maxConnections:\"25\",trxControlMode:locks,trxIsolationLevel:read_committed,type:Memory,tableType:Memory,mode:embedded}", + "hsqldb" ); storeNames.add( storeName ); return storeName; } - default String deployMonetDb( boolean deployStoresUsingDocker ) throws ExecutorException { String config; String name; @@ -83,7 +86,8 @@ default String deployMonetDb( boolean deployStoresUsingDocker ) throws ExecutorE deployStore( name, "org.polypheny.db.adapter.jdbc.stores.MonetdbStore", - config ); + config, + "monetdb" ); storeNames.add( name ); return name; } @@ -102,7 +106,8 @@ default String deployPostgres( boolean deployStoresUsingDocker ) throws Executor deployStore( name, "org.polypheny.db.adapter.jdbc.stores.PostgresqlStore", - config ); + config, + "postgres" ); storeNames.add( name ); return name; } @@ -121,7 +126,8 @@ default String deployCassandra( boolean deployStoresUsingDocker ) throws Executo deployStore( name, "org.polypheny.db.adapter.cassandra.CassandraStore", - config ); + config, + "cassandra" ); storeNames.add( name ); return name; } @@ -132,7 +138,8 @@ default String deployFileStore() throws ExecutorException { deployStore( storeName, "org.polypheny.db.adapter.file.FileStore", - "{\"mode\":\"embedded\"}" ); + "{\"mode\":\"embedded\"}", + "file" ); storeNames.add( storeName ); return storeName; } @@ -143,7 +150,8 @@ default String deployCottontail() throws ExecutorException { deployStore( storeName, "org.polypheny.db.adapter.cottontail.CottontailStore", - "{\"type\":\"Embedded\",\"host\":\"localhost\",\"port\":\"" + nextPort.getAndIncrement() + "\",\"database\":\"cottontail\",\"engine\":\"MAPDB\",\"mode\":\"embedded\"}" ); + "{\"type\":\"Embedded\",\"host\":\"localhost\",\"port\":\"" + nextPort.getAndIncrement() + "\",\"database\":\"cottontail\",\"engine\":\"MAPDB\",\"mode\":\"embedded\"}", + "cottontail" ); storeNames.add( storeName ); return storeName; } @@ -155,7 +163,8 @@ default String deployMongoDb() throws ExecutorException { deployStore( storeName, "org.polypheny.db.adapter.mongodb.MongoStore", - config ); + config, + "mongodb" ); storeNames.add( storeName ); return storeName; } @@ -166,11 +175,15 @@ default String deployNeo4j() throws ExecutorException { deployStore( storeName, "org.polypheny.db.adapter.neo4j.Neo4jStore", - config ); + config, + "neo4j" ); storeNames.add( storeName ); return storeName; } + // At the moment it is only possible to set Policies for the whole system + void setPolicies( String clauseName, String value ) throws ExecutorException; + void setConfig( String key, String value ); @@ -207,58 +220,19 @@ public PolyphenyDbInstance( PolyphenyControlConnector polyphenyControlConnector, log.error( "Error while logging polypheny version", e ); } - // Configure data stores - PolyphenyDbExecutor executor = (PolyphenyDbExecutor) executorFactory.createExecutorInstance(); - try { - // Remove hsqldb store - executor.dropStore( "hsqldb" ); - // Deploy stores - for ( String store : config.dataStores ) { - switch ( store ) { - case "hsqldb": - executor.deployHsqldb(); - break; - case "postgres": - if ( !config.deployStoresUsingDocker ) { - PostgresInstance.reset(); - } - executor.deployPostgres( config.deployStoresUsingDocker ); - break; - case "monetdb": - if ( !config.deployStoresUsingDocker ) { - MonetdbInstance.reset(); - } - executor.deployMonetDb( config.deployStoresUsingDocker ); - break; - case "cassandra": - executor.deployCassandra( config.deployStoresUsingDocker ); - break; - case "file": - executor.deployFileStore(); - break; - case "cottontail": - executor.deployCottontail(); - break; - case "mongodb": - executor.deployMongoDb(); - break; - case "neo4j": - executor.deployNeo4j(); - break; - default: - throw new RuntimeException( "Unknown data store: " + store ); - } - } - executor.executeCommit(); - } catch ( ExecutorException e ) { - throw new RuntimeException( "Exception while configuring stores", e ); - } finally { - try { - executor.closeConnection(); - } catch ( ExecutorException e ) { - log.error( "Exception while closing connection", e ); - } + // Deploy Stores + List datastores; + if ( !config.multipleDataStores.isEmpty() ) { + datastores = config.multipleDataStores; + } else { + datastores = config.dataStores; } + boolean useDocker = config.deployStoresUsingDocker; + + deployStores( useDocker, executorFactory, datastores ); + + // Update polypheny config + PolyphenyDbExecutor executor = (PolyphenyDbExecutor) executorFactory.createExecutorInstance(); pushConfiguration( executorFactory, config ); @@ -418,6 +392,32 @@ protected void pushConfiguration( ExecutorFactory executorFactory, AbstractConfi log.error( "Exception while closing connection", e ); } } + + // Set Policies + if ( config.usePolicies != null && config.usePolicies.equals( "PolicyAndSelfAdaptiveness" ) ) { + executor = (PolyphenyDbExecutor) executorFactory.createExecutorInstance(); + try { + for ( String storePolicy : config.storePolicies ) { + if ( storePolicy != null && !storePolicy.equals( "NONE" ) ) { + executor.setPolicies( storePolicy, "true" ); + } + } + for ( String selfAdaptingPolicy : config.selfAdaptingPolicies ) { + if ( selfAdaptingPolicy != null && !selfAdaptingPolicy.equals( "NONE" ) ) { + executor.setPolicies( selfAdaptingPolicy, "true" ); + } + } + executor.executeCommit(); + } catch ( ExecutorException e ) { + throw new RuntimeException( "Not possible to set Policies", e ); + } finally { + try { + executor.closeConnection(); + } catch ( ExecutorException e ) { + log.error( "Exception while closing connection", e ); + } + } + } } @@ -444,6 +444,63 @@ protected void configurePolyphenyControl( PolyphenyControlConnector polyphenyCon } + public static void deployStores( Boolean useDocker, ExecutorFactory executorFactory, List dataStores ) { + // Configure data stores + PolyphenyDbExecutor executor = (PolyphenyDbExecutor) executorFactory.createExecutorInstance(); + + try { + // Remove hsqldb store + executor.dropStore( "hsqldb" ); + // Deploy stores + for ( String store : dataStores ) { + switch ( store ) { + case "hsqldb": + executor.deployHsqldb(); + break; + case "postgres": + if ( !useDocker ) { + PostgresInstance.reset(); + } + executor.deployPostgres( useDocker ); + break; + case "monetdb": + if ( !useDocker ) { + MonetdbInstance.reset(); + } + executor.deployMonetDb( useDocker); + break; + case "cassandra": + executor.deployCassandra( useDocker ); + break; + case "file": + executor.deployFileStore(); + break; + case "cottontail": + executor.deployCottontail(); + break; + case "mongodb": + executor.deployMongoDb(); + break; + case "neo4j": + executor.deployNeo4j(); + break; + default: + throw new RuntimeException( "Unknown data store: " + store ); + } + } + executor.executeCommit(); + } catch ( ExecutorException e ) { + throw new RuntimeException( "Exception while configuring stores", e ); + } finally { + try { + executor.closeConnection(); + } catch ( ExecutorException e ) { + log.error( "Exception while closing connection", e ); + } + } + } + + @Override public void tearDown() { stopPolypheny( polyphenyControlConnector ); diff --git a/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbHttpExecutor.java b/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbHttpExecutor.java index 9242306e..690d1f60 100644 --- a/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbHttpExecutor.java +++ b/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbHttpExecutor.java @@ -101,11 +101,11 @@ public void dropStore( String name ) throws ExecutorException { @Override - public void deployStore( String name, String clazz, String config ) throws ExecutorException { + public void deployStore( String name, String clazz, String config, String store ) throws ExecutorException { PolyphenyDbJdbcExecutor executor = null; try { executor = jdbcExecutorFactory.createExecutorInstance( csvWriter ); - executor.deployStore( name, clazz, config ); + executor.deployStore( name, clazz, config, store ); executor.executeCommit(); } catch ( ExecutorException e ) { throw new ExecutorException( "Error while executing query via JDBC", e ); diff --git a/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbJdbcExecutor.java b/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbJdbcExecutor.java index b29a595d..9032c40b 100644 --- a/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbJdbcExecutor.java +++ b/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbJdbcExecutor.java @@ -26,6 +26,9 @@ import java.sql.DriverManager; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Properties; import lombok.extern.slf4j.Slf4j; import org.polypheny.simpleclient.main.CsvWriter; @@ -35,7 +38,6 @@ @Slf4j public class PolyphenyDbJdbcExecutor extends JdbcExecutor implements PolyphenyDbExecutor { - private PolyphenyDbJdbcExecutor( String polyphenyHost, CsvWriter csvWriter, boolean prepareStatements ) { super( csvWriter, prepareStatements ); @@ -73,11 +75,27 @@ public void dropStore( String name ) throws ExecutorException { @Override - public void deployStore( String name, String clazz, String config ) throws ExecutorException { + public void deployStore( String name, String clazz, String config, String store ) throws ExecutorException { + + if ( dataStoreNames.containsKey( store ) ) { + List stringNames = new ArrayList<>( dataStoreNames.get( store ) ); + stringNames.add( name ); + dataStoreNames.put( store, stringNames ); + } else { + dataStoreNames.put( store, Collections.singletonList( name ) ); + } + executeQuery( new RawQuery( "ALTER ADAPTERS ADD \"" + name + "\" USING '" + clazz + "' WITH '" + config + "'", null, false ) ); } + // At the moment it is only possible to set Policies for Polypheny + @Override + public void setPolicies( String clauseName, String value ) throws ExecutorException { + executeQuery( new RawQuery( "ALTER POLICY " + clauseName + " SET " + value, null, false ) ); + } + + @Override public void setConfig( String key, String value ) { try { diff --git a/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbMongoQlExecutor.java b/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbMongoQlExecutor.java index addf4563..893cbde3 100644 --- a/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbMongoQlExecutor.java +++ b/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbMongoQlExecutor.java @@ -24,12 +24,18 @@ package org.polypheny.simpleclient.executor; +import static org.polypheny.simpleclient.executor.PolyphenyDbJdbcExecutor.commitAndCloseJdbcExecutor; + +import com.google.gson.JsonObject; +import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; import kong.unirest.HttpRequest; import kong.unirest.HttpResponse; import kong.unirest.JsonNode; +import kong.unirest.Unirest; import kong.unirest.UnirestException; import kong.unirest.json.JSONArray; import lombok.extern.slf4j.Slf4j; @@ -73,7 +79,7 @@ public long executeQuery( Query query ) throws ExecutorException { } time = System.nanoTime() - start; if ( csvWriter != null ) { - csvWriter.appendToCsv( request.getUrl(), time ); + csvWriter.appendToCsv( query.getMongoQl(), time ); } } catch ( UnirestException e ) { throw new ExecutorException( e ); @@ -83,6 +89,28 @@ public long executeQuery( Query query ) throws ExecutorException { } + private HttpRequest buildQuery( String mql ) { + JsonObject data = new JsonObject(); + data.addProperty( "query", mql ); + data.addProperty( "database", "test" ); + + return Unirest.post( "{protocol}://{host}:{port}/mongo" ) + .header( "Content-Type", "application/json" ) + .body( data ); + + } + + + private HttpRequest getRequest( String mql ) { + HttpRequest request = buildQuery( mql ); + request.basicAuth( "pa", "" ); + request.routeParam( "protocol", "http" ); + request.routeParam( "host", "127.0.0.1" ); + request.routeParam( "port", "13137" ); + return request; + } + + @Override public long executeQueryAndGetNumber( Query query ) throws ExecutorException { query.debug(); @@ -99,7 +127,7 @@ public long executeQueryAndGetNumber( Query query ) throws ExecutorException { throw new ExecutorException( "Error while executing MongoQl query. Message: " + result.getStatusText() + " | URL: " + request.getUrl() ); } if ( csvWriter != null ) { - csvWriter.appendToCsv( request.getUrl(), System.nanoTime() - start ); + csvWriter.appendToCsv( query.getMongoQl(), System.nanoTime() - start ); } // Get result of a count query JSONArray res = result.getBody().getObject().getJSONArray( "data" ); @@ -157,6 +185,80 @@ public void executeInsertList( List batchList, AbstractConfig c } + @Override + public void flushCsvWriter() { + if ( csvWriter != null ) { + try { + csvWriter.flush(); + } catch ( IOException e ) { + log.warn( "Exception while flushing csv writer", e ); + } + } + } + + + @Override + public void dropStore( String name ) throws ExecutorException { + PolyphenyDbJdbcExecutor executor = null; + try { + executor = jdbcExecutorFactory.createExecutorInstance( csvWriter ); + executor.dropStore( name ); + executor.executeCommit(); + } catch ( ExecutorException e ) { + throw new ExecutorException( "Error while executing query via JDBC", e ); + } finally { + commitAndCloseJdbcExecutor( executor ); + } + } + + + @Override + public void deployStore( String name, String clazz, String config, String store ) throws ExecutorException { + if ( dataStoreNames.containsKey( store ) ) { + List stringNames = new ArrayList<>( dataStoreNames.get( store ) ); + stringNames.add( name ); + dataStoreNames.put( store, stringNames ); + } else { + dataStoreNames.put( store, Collections.singletonList( name ) ); + } + PolyphenyDbJdbcExecutor executor = null; + try { + executor = jdbcExecutorFactory.createExecutorInstance( csvWriter ); + executor.deployStore( name, clazz, config, store ); + executor.executeCommit(); + } catch ( ExecutorException e ) { + throw new ExecutorException( "Error while executing query via JDBC", e ); + } finally { + commitAndCloseJdbcExecutor( executor ); + } + } + + + @Override + public void setPolicies( String clauseName, String value ) throws ExecutorException { + // NoOp + } + + + @Override + public void setConfig( String key, String value ) { + PolyphenyDbJdbcExecutor executor = null; + try { + executor = jdbcExecutorFactory.createExecutorInstance( csvWriter ); + executor.setConfig( key, value ); + executor.executeCommit(); + } catch ( ExecutorException e ) { + log.error( "Exception while setting config \"" + key + "\"!", e ); + } finally { + try { + commitAndCloseJdbcExecutor( executor ); + } catch ( ExecutorException e ) { + log.error( "Exception while closing JDBC executor", e ); + } + } + } + + public static class PolyphenyDbMongoQlExecutorFactory extends ExecutorFactory { private final String host; diff --git a/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbRestExecutor.java b/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbRestExecutor.java index 9c1059b1..744d5503 100644 --- a/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbRestExecutor.java +++ b/src/main/java/org/polypheny/simpleclient/executor/PolyphenyDbRestExecutor.java @@ -27,6 +27,7 @@ import com.google.gson.JsonObject; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; @@ -232,11 +233,18 @@ public void dropStore( String name ) throws ExecutorException { @Override - public void deployStore( String name, String clazz, String config ) throws ExecutorException { + public void deployStore( String name, String clazz, String config, String store ) throws ExecutorException { + if ( dataStoreNames.containsKey( store ) ) { + List stringNames = new ArrayList<>( dataStoreNames.get( store ) ); + stringNames.add( name ); + dataStoreNames.put( store, stringNames ); + } else { + dataStoreNames.put( store, Collections.singletonList( name ) ); + } PolyphenyDbJdbcExecutor executor = null; try { executor = jdbcExecutorFactory.createExecutorInstance( csvWriter ); - executor.deployStore( name, clazz, config ); + executor.deployStore( name, clazz, config, store ); executor.executeCommit(); } catch ( ExecutorException e ) { throw new ExecutorException( "Error while executing query via JDBC", e ); @@ -246,6 +254,12 @@ public void deployStore( String name, String clazz, String config ) throws Execu } + @Override + public void setPolicies( String clauseName, String value ) throws ExecutorException { + // NoOp + } + + @Override public void setConfig( String key, String value ) { PolyphenyDbJdbcExecutor executor = null; diff --git a/src/main/java/org/polypheny/simpleclient/main/ChronosAgent.java b/src/main/java/org/polypheny/simpleclient/main/ChronosAgent.java index 980ddd4d..32709846 100644 --- a/src/main/java/org/polypheny/simpleclient/main/ChronosAgent.java +++ b/src/main/java/org/polypheny/simpleclient/main/ChronosAgent.java @@ -46,8 +46,8 @@ import org.polypheny.simpleclient.cli.ChronosCommand; import org.polypheny.simpleclient.executor.CottontaildbExecutor.CottontailExecutorFactory; import org.polypheny.simpleclient.executor.CottontaildbExecutor.CottontailInstance; -import org.polypheny.simpleclient.executor.Executor; import org.polypheny.simpleclient.executor.Executor.DatabaseInstance; +import org.polypheny.simpleclient.executor.Executor.ExecutorFactory; import org.polypheny.simpleclient.executor.MonetdbExecutor.MonetdbExecutorFactory; import org.polypheny.simpleclient.executor.MonetdbExecutor.MonetdbInstance; import org.polypheny.simpleclient.executor.OltpBenchPolyphenyDbExecutor.OltpBenchPolyphenyDbExecutorFactory; @@ -68,6 +68,9 @@ import org.polypheny.simpleclient.scenario.docbench.DocBenchConfig; import org.polypheny.simpleclient.scenario.gavel.Gavel; import org.polypheny.simpleclient.scenario.gavel.GavelConfig; +import org.polypheny.simpleclient.scenario.gavelNG.GavelNG; +import org.polypheny.simpleclient.scenario.gavelNG.GavelNGConfig; +import org.polypheny.simpleclient.scenario.gavelNG.GavelNGProfile; import org.polypheny.simpleclient.scenario.graph.GraphBench; import org.polypheny.simpleclient.scenario.graph.GraphBenchConfig; import org.polypheny.simpleclient.scenario.knnbench.KnnBench; @@ -178,40 +181,46 @@ protected Object prepare( ChronosJob chronosJob, final File inputDirectory, fina } // Create Executor Factory - Executor.ExecutorFactory executorFactory; - switch ( parsedConfig.get( "store" ) ) { - case "polypheny": - executorFactory = new PolyphenyDbMultiExecutorFactory( ChronosCommand.hostname ); - break; - case "polypheny-jdbc": - executorFactory = new PolyphenyDbJdbcExecutorFactory( ChronosCommand.hostname, Boolean.parseBoolean( parsedConfig.get( "prepareStatements" ) ) ); - break; - case "polypheny-rest": - executorFactory = new PolyphenyDbRestExecutorFactory( ChronosCommand.hostname ); - break; - case "polypheny-mongoql": - executorFactory = new PolyphenyDbMongoQlExecutorFactory( ChronosCommand.hostname ); - break; - case "polypheny-cypher": - executorFactory = new PolyphenyDbCypherExecutorFactory( ChronosCommand.hostname ); - break; - case "postgres": - executorFactory = new PostgresExecutorFactory( ChronosCommand.hostname, Boolean.parseBoolean( parsedConfig.get( "prepareStatements" ) ) ); - break; - case "monetdb": - executorFactory = new MonetdbExecutorFactory( ChronosCommand.hostname, Boolean.parseBoolean( parsedConfig.get( "prepareStatements" ) ) ); - break; - case "cottontail": - executorFactory = new CottontailExecutorFactory( ChronosCommand.hostname ); - break; - case "oltpbench-polypheny": - executorFactory = new OltpBenchPolyphenyDbExecutorFactory( ChronosCommand.hostname ); - break; - case "oltpbench-postgres": - executorFactory = new OltpBenchPostgresExecutorFactory( ChronosCommand.hostname ); - break; - default: - throw new RuntimeException( "Unknown system: " + parsedConfig.get( "store" ) ); + ExecutorFactory executorFactory; + ExecutorFactory executorFactoryMONGODB = null; + if ( parsedConfig.get( "scenario" ).equals( "gavelng" ) ) { + executorFactory = new PolyphenyDbJdbcExecutorFactory( ChronosCommand.hostname, Boolean.parseBoolean( parsedConfig.get( "prepareStatements" ) ) ); + executorFactoryMONGODB = new PolyphenyDbMongoQlExecutorFactory( ChronosCommand.hostname ); + } else { + switch ( parsedConfig.get( "store" ) ) { + case "polypheny": + executorFactory = new PolyphenyDbMultiExecutorFactory( ChronosCommand.hostname ); + break; + case "polypheny-jdbc": + executorFactory = new PolyphenyDbJdbcExecutorFactory( ChronosCommand.hostname, Boolean.parseBoolean( parsedConfig.get( "prepareStatements" ) ) ); + break; + case "polypheny-rest": + executorFactory = new PolyphenyDbRestExecutorFactory( ChronosCommand.hostname ); + break; + case "polypheny-mongoql": + executorFactory = new PolyphenyDbMongoQlExecutorFactory( ChronosCommand.hostname ); + break; + case "polypheny-cypher": + executorFactory = new PolyphenyDbCypherExecutorFactory( ChronosCommand.hostname ); + break; + case "postgres": + executorFactory = new PostgresExecutorFactory( ChronosCommand.hostname, Boolean.parseBoolean( parsedConfig.get( "prepareStatements" ) ) ); + break; + case "monetdb": + executorFactory = new MonetdbExecutorFactory( ChronosCommand.hostname, Boolean.parseBoolean( parsedConfig.get( "prepareStatements" ) ) ); + break; + case "cottontail": + executorFactory = new CottontailExecutorFactory( ChronosCommand.hostname ); + break; + case "oltpbench-polypheny": + executorFactory = new OltpBenchPolyphenyDbExecutorFactory( ChronosCommand.hostname ); + break; + case "oltpbench-postgres": + executorFactory = new OltpBenchPostgresExecutorFactory( ChronosCommand.hostname ); + break; + default: + throw new RuntimeException( "Unknown system: " + parsedConfig.get( "store" ) ); + } } Scenario scenario; @@ -221,6 +230,11 @@ protected Object prepare( ChronosJob chronosJob, final File inputDirectory, fina config = new GavelConfig( parsedConfig ); scenario = new Gavel( executorFactory, (GavelConfig) config, true, dumpQueryList, queryMode ); break; + case "gavelng": + config = new GavelNGConfig( parsedConfig ); + GavelNGProfile profile = new GavelNGProfile( parsedConfig ); + scenario = new GavelNG( executorFactory, executorFactoryMONGODB, (GavelNGConfig) config, profile, true, dumpQueryList, queryMode ); + break; case "knnBench": config = new KnnBenchConfig( parsedConfig ); scenario = new KnnBench( executorFactory, (KnnBenchConfig) config, true, dumpQueryList ); diff --git a/src/main/java/org/polypheny/simpleclient/main/GavelNGScenario.java b/src/main/java/org/polypheny/simpleclient/main/GavelNGScenario.java new file mode 100644 index 00000000..db45bec8 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/main/GavelNGScenario.java @@ -0,0 +1,111 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.main; + +import java.io.File; +import java.io.IOException; +import java.util.Objects; +import java.util.Properties; +import lombok.extern.slf4j.Slf4j; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.executor.Executor.ExecutorFactory; +import org.polypheny.simpleclient.scenario.gavelNG.GavelNG; +import org.polypheny.simpleclient.scenario.gavelNG.GavelNGConfig; +import org.polypheny.simpleclient.scenario.gavelNG.GavelNGProfile; + + +@Slf4j +public class GavelNGScenario { + + public static void schema( ExecutorFactory jdbcExecutorFactory, ExecutorFactory mqlExecutorFactory, boolean commitAfterEveryQuery, QueryMode queryMode ) { + GavelNGConfig config = new GavelNGConfig( getProperties(), 1); + GavelNGProfile profile = new GavelNGProfile( getProfileProperties() ); + + GavelNG gavelNG = new GavelNG( jdbcExecutorFactory, mqlExecutorFactory, config, profile, commitAfterEveryQuery, false, queryMode); + gavelNG.createSchema( null, true ); + } + + + public static void data( ExecutorFactory jdbcExecutorFactory, ExecutorFactory mqlExecutorFactory, int multiplier, boolean commitAfterEveryQuery, QueryMode queryMode ) { + GavelNGConfig config = new GavelNGConfig( getProperties(), multiplier ); + GavelNGProfile profile = new GavelNGProfile( getProfileProperties() ); + GavelNG gavelNG = new GavelNG( jdbcExecutorFactory, mqlExecutorFactory, config, profile, commitAfterEveryQuery, false, queryMode ); + + ProgressReporter progressReporter = new ProgressBar( config.numberOfThreads, config.progressReportBase ); + gavelNG.generateData( null, progressReporter ); + } + + + public static void workload( ExecutorFactory jdbcExecutorFactory, ExecutorFactory mqlExecutorFactory, int multiplier, boolean commitAfterEveryQuery, boolean writeCsv, boolean dumpQueryList, QueryMode queryMode ) { + GavelNGConfig config = new GavelNGConfig( getProperties(), multiplier ); + GavelNGProfile profile = new GavelNGProfile( getProfileProperties() ); + GavelNG gavelNG = new GavelNG( jdbcExecutorFactory, mqlExecutorFactory, config, profile, commitAfterEveryQuery, dumpQueryList, queryMode ); + + final CsvWriter csvWriter; + if ( writeCsv ) { + csvWriter = new CsvWriter( "results.csv" ); + } else { + csvWriter = null; + } + ProgressReporter progressReporter = new ProgressBar( config.numberOfThreads, config.progressReportBase ); + + gavelNG.execute( progressReporter, csvWriter, new File( "." ), config.numberOfThreads ); + } + + + public static void warmup( ExecutorFactory jdbcExecutorFactory, ExecutorFactory mqlExecutorFactory, int multiplier, boolean commitAfterEveryQuery, boolean dumpQueryList, QueryMode queryMode ) { + GavelNGConfig config = new GavelNGConfig( getProperties(), 1 ); + GavelNGProfile profile = new GavelNGProfile( getProfileProperties() ); + GavelNG gavelNG = new GavelNG( jdbcExecutorFactory, mqlExecutorFactory, config, profile, commitAfterEveryQuery, dumpQueryList, queryMode ); + + ProgressReporter progressReporter = new ProgressBar( config.numberOfThreads, config.progressReportBase ); + + gavelNG.warmUp( progressReporter ); + } + + + private static Properties getProperties() { + Properties props = new Properties(); + try { + props.load( Objects.requireNonNull( ClassLoader.getSystemResourceAsStream( "org/polypheny/simpleclient/scenario/gavelNG/gavelNG.properties" ) ) ); + } catch ( IOException e ) { + log.error( "Exception while reading properties file", e ); + } + return props; + } + + + private static Properties getProfileProperties() { + Properties props = new Properties(); + try { + props.load( Objects.requireNonNull( ClassLoader.getSystemResourceAsStream( "org/polypheny/simpleclient/scenario/gavelNG/gavelNGProfile.properties" ) ) ); + } catch ( IOException e ) { + log.error( "Exception while reading properties file", e ); + } + return props; + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/query/QueryListEntry.java b/src/main/java/org/polypheny/simpleclient/query/QueryListEntry.java index 4dca243a..9cb198a6 100644 --- a/src/main/java/org/polypheny/simpleclient/query/QueryListEntry.java +++ b/src/main/java/org/polypheny/simpleclient/query/QueryListEntry.java @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2019-2021 The Polypheny Project + * Copyright (c) 2019-2022 The Polypheny Project * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), to deal @@ -25,15 +25,32 @@ package org.polypheny.simpleclient.query; +import lombok.Getter; +import org.polypheny.simpleclient.scenario.gavelNG.GavelNG.QueryLanguage; + public class QueryListEntry { public final Query query; public final int templateId; + public final long delay; + @Getter + public final QueryLanguage queryLanguage; public QueryListEntry( Query query, int templateId ) { this.query = query; this.templateId = templateId; + this.delay = 0; + this.queryLanguage = QueryLanguage.SQL; } + + public QueryListEntry( Query query, int templateId, int delay, QueryLanguage queryLanguage ) { + this.query = query; + this.templateId = templateId; + this.delay = delay * 1000L; + this.queryLanguage = queryLanguage; + } + + } diff --git a/src/main/java/org/polypheny/simpleclient/scenario/AbstractConfig.java b/src/main/java/org/polypheny/simpleclient/scenario/AbstractConfig.java index ea8b9e23..84eb1182 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/AbstractConfig.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/AbstractConfig.java @@ -70,6 +70,13 @@ public abstract class AbstractConfig { public final int progressReportBase = 100; + // Only used for GavelNG + public List multipleDataStores = new ArrayList<>(); + public final List storePolicies = new ArrayList<>(); + public final List selfAdaptingPolicies = new ArrayList<>(); + public String usePolicies = null; + public boolean statisticActiveTracking = false; + protected AbstractConfig( String scenario, String system, Properties properties ) { this.scenario = scenario; diff --git a/src/main/java/org/polypheny/simpleclient/scenario/Scenario.java b/src/main/java/org/polypheny/simpleclient/scenario/Scenario.java index 8c98c5ea..dedc0800 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/Scenario.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/Scenario.java @@ -50,6 +50,7 @@ public abstract class Scenario { @Getter protected final ExecutorFactory executorFactory; + protected final ExecutorFactory mqlExecutorFactory; protected final boolean commitAfterEveryQuery; protected final boolean dumpQueryList; protected final QueryMode queryMode; @@ -57,6 +58,15 @@ public abstract class Scenario { protected Scenario( ExecutorFactory executorFactory, boolean commitAfterEveryQuery, boolean dumpQueryList, QueryMode queryMode ) { this.executorFactory = executorFactory; + this.mqlExecutorFactory = null; + this.commitAfterEveryQuery = commitAfterEveryQuery; + this.dumpQueryList = dumpQueryList; + this.queryMode = queryMode; + } + + protected Scenario( ExecutorFactory jdbcExecutorFactory, ExecutorFactory mqlExecutorFactory, boolean commitAfterEveryQuery, boolean dumpQueryList, QueryMode queryMode ) { + this.executorFactory = jdbcExecutorFactory; + this.mqlExecutorFactory = mqlExecutorFactory; this.commitAfterEveryQuery = commitAfterEveryQuery; this.dumpQueryList = dumpQueryList; this.queryMode = queryMode; diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/DataGeneratorGavelNG.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/DataGeneratorGavelNG.java new file mode 100644 index 00000000..35d30357 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/DataGeneratorGavelNG.java @@ -0,0 +1,265 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG; + + +import com.devskiller.jfairy.Fairy; +import com.devskiller.jfairy.producer.DateProducer; +import com.devskiller.jfairy.producer.text.TextProducer; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicInteger; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.polypheny.simpleclient.executor.Executor; +import org.polypheny.simpleclient.executor.ExecutorException; +import org.polypheny.simpleclient.main.ProgressReporter; +import org.polypheny.simpleclient.query.BatchableInsert; +import org.polypheny.simpleclient.scenario.gavelNG.GavelNG.DataGenerationThreadMonitor; +import org.polypheny.simpleclient.scenario.gavelNG.GavelNG.QueryLanguage; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.InsertAuction; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.InsertBid; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.InsertCategory; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.InsertCondition; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.InsertPicture; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.InsertUser; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.TruncateAuction; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.TruncateBid; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.TruncateCategory; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.TruncateCondition; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.TruncatePicture; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.TruncateUser; + + +@Slf4j +class DataGeneratorGavelNG { + + private static final AtomicInteger nextAuctionId = new AtomicInteger( 1 ); + + private final Executor executor; + private final Executor executorMongoDB; + private final GavelNGConfig config; + private final ProgressReporter progressReporter; + private final List batchList; + + @Getter + private final DataGenerationThreadMonitor threadMonitor; + private boolean aborted; + + + DataGeneratorGavelNG( Executor executor, Executor executorMongoDB, GavelNGConfig config, ProgressReporter progressReporter, DataGenerationThreadMonitor threadMonitor ) { + this.executor = executor; + this.executorMongoDB = executorMongoDB; + this.config = config; + this.progressReporter = progressReporter; + this.batchList = new LinkedList<>(); + this.threadMonitor = threadMonitor; + threadMonitor.registerDataGenerator( this ); + this.aborted = false; + } + + + void truncateTables( QueryLanguage queryLanguage ) throws ExecutorException { + Executor theExecutor; + log.info( "Truncate Tables" ); + if ( queryLanguage == QueryLanguage.MQL ) { + theExecutor = executorMongoDB; + } else { + theExecutor = executor; + } + theExecutor.executeQuery( (new TruncateCategory()).getNewQuery() ); + theExecutor.executeQuery( (new TruncateUser()).getNewQuery() ); + theExecutor.executeQuery( (new TruncateAuction()).getNewQuery() ); + theExecutor.executeQuery( (new TruncateBid()).getNewQuery() ); + theExecutor.executeQuery( (new TruncatePicture()).getNewQuery() ); + theExecutor.executeQuery( (new TruncateCondition()).getNewQuery() ); + } + + + void generateCategories( QueryLanguage queryLanguage ) throws ExecutorException { + int numberOfCategories = config.numberOfCategories; + InsertCategory queryBuilder = new InsertCategory(); + for ( int i = 0; i < numberOfCategories; i++ ) { + if ( aborted ) { + break; + } + addToInsertList( queryBuilder.getNewQuery(), queryLanguage ); + } + executeInsertList( queryLanguage ); + } + + + void generateUsers( int numberOfUsers, QueryLanguage queryLanguage ) throws ExecutorException { + int mod = numberOfUsers / progressReporter.base; + InsertUser queryBuilder = new InsertUser(); + for ( int i = 0; i < numberOfUsers; i++ ) { + if ( aborted ) { + break; + } + addToInsertList( queryBuilder.getNewQuery(), queryLanguage ); + if ( (i % mod) == 0 ) { + progressReporter.updateProgress(); + } + } + executeInsertList( queryLanguage ); + } + + + void generateConditions( QueryLanguage queryLanguage ) throws ExecutorException { + int numberOfConditions = config.numberOfConditions; + + InsertCondition queryBuilder = new InsertCondition(); + for ( int i = 0; i < numberOfConditions; i++ ) { + if ( aborted ) { + break; + } + addToInsertList( queryBuilder.getNewQuery(), queryLanguage ); + } + executeInsertList( queryLanguage ); + } + + + void generateAuctions( int start, int end, QueryLanguage queryLanguage ) throws ExecutorException { + int mod = ((end - start) + 1) / progressReporter.base; + + int numberOfCategories = config.numberOfCategories; + int numberOfUsers = config.numberOfUsers; + int auctionTitleMinLength = config.auctionTitleMinLength; + int auctionTitleMaxLength = config.auctionTitleMaxLength; + int auctionDescriptionMinLength = config.auctionDescriptionMinLength; + int auctionDescriptionMaxLength = config.auctionDescriptionMaxLength; + int auctionDateMaxYearsInPast = config.auctionDateMaxYearsInPast; + int auctionNumberOfDays = config.auctionNumberOfDays; + int minNumberOfBidsPerAuction = config.minNumberOfBidsPerAuction; + int maxNumberOfBidsPerAuction = config.maxNumberOfBidsPerAuction; + int minNumberOfPicturesPerAuction = config.minNumberOfPicturesPerAuction; + int maxNumberOfPicturesPerAuction = config.maxNumberOfPicturesPerAuction; + + Fairy fairy = Fairy.create(); + TextProducer text = fairy.textProducer(); + DateProducer dateProducer = fairy.dateProducer(); + + LocalDateTime startDate; + LocalDateTime endDate; + int user; + int numberOfBids; + int numberOfPictures; + int category; + String title; + String description; + for ( int i = start; i <= end; i++ ) { + if ( aborted ) { + break; + } + if ( (i % mod) == 0 ) { + progressReporter.updateProgress(); + } + // create an auction + startDate = dateProducer.randomDateInThePast( auctionDateMaxYearsInPast ).withNano( 0 ); + endDate = startDate.plusDays( auctionNumberOfDays ); + user = ThreadLocalRandom.current().nextInt( 1, numberOfUsers + 1 ); + category = ThreadLocalRandom.current().nextInt( 1, numberOfCategories + 1 ); + title = text.latinWord( ThreadLocalRandom.current().nextInt( auctionTitleMinLength, auctionTitleMaxLength + 1 ) ); + description = text.paragraph( ThreadLocalRandom.current().nextInt( auctionDescriptionMinLength, auctionDescriptionMaxLength + 1 ) ); + int auctionId = nextAuctionId.getAndIncrement(); + int conditionId = nextAuctionId.getAndIncrement(); + addToInsertList( new InsertAuction( auctionId, user, category, conditionId, startDate, endDate, title, description ).getNewQuery(), queryLanguage ); + executeInsertList( queryLanguage ); + + // create bids for that auction + numberOfBids = ThreadLocalRandom.current().nextInt( minNumberOfBidsPerAuction, maxNumberOfBidsPerAuction ); + int lastBid = 0; + int amount; + int u; + LocalDateTime dt; + LocalDateTime dtLast = startDate; + + // Bids should be in a temporal order. In order to avoid the case where it randomly pics the end date we calculate + // an offset of seconds we need to add to the end data in every iteration. This leeds to a somehow even distribution of the + // bits over time. + long difference = ChronoUnit.SECONDS.between( startDate, endDate ); + long offset = difference / numberOfBids; + + for ( int j = 0; j < numberOfBids; j++ ) { + amount = ThreadLocalRandom.current().nextInt( lastBid + 1, lastBid + 1000 ); + u = ThreadLocalRandom.current().nextInt( 1, numberOfUsers + 1 ); + if ( u == user ) { + // no bids on your own auction + if ( u < numberOfUsers ) { + u++; + } else { + u--; + } + } + dt = dateProducer.randomDateBetweenTwoDates( dtLast, endDate.minusSeconds( offset * (numberOfBids - (j + 1)) ) ); + lastBid = amount; + amount = amount * 100; + addToInsertList( new InsertBid( auctionId, u, amount, dt ).getNewQuery(), queryLanguage ); + dtLast = dt; + } + executeInsertList( queryLanguage ); + + // create pictures + InsertPicture pictureBuilder = new InsertPicture( auctionId ); + numberOfPictures = ThreadLocalRandom.current().nextInt( minNumberOfPicturesPerAuction, maxNumberOfPicturesPerAuction ); + for ( int j = 0; j < numberOfPictures; j++ ) { + addToInsertList( pictureBuilder.getNewQuery(), queryLanguage ); + } + executeInsertList( queryLanguage ); + } + + } + + + private void addToInsertList( BatchableInsert query, QueryLanguage queryLanguage ) throws ExecutorException { + batchList.add( query ); + if ( batchList.size() >= config.maxBatchSize ) { + executeInsertList( queryLanguage ); + } + } + + + private void executeInsertList( QueryLanguage queryLanguage ) throws ExecutorException { + Executor theExecutor; + if ( queryLanguage == QueryLanguage.MQL ) { + theExecutor = executorMongoDB; + } else { + theExecutor = executor; + } + theExecutor.executeInsertList( batchList, config ); + theExecutor.executeCommit(); + batchList.clear(); + } + + + public void abort() { + aborted = true; + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/GavelNG.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/GavelNG.java new file mode 100644 index 00000000..879d845f --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/GavelNG.java @@ -0,0 +1,821 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG; + + +import com.google.common.base.Joiner; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Random; +import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.executor.Executor; +import org.polypheny.simpleclient.executor.Executor.DatabaseInstance; +import org.polypheny.simpleclient.executor.ExecutorException; +import org.polypheny.simpleclient.executor.JdbcExecutor; +import org.polypheny.simpleclient.executor.PolyphenyDbExecutor; +import org.polypheny.simpleclient.executor.PolyphenyDbMongoQlExecutor; +import org.polypheny.simpleclient.main.ChronosAgent; +import org.polypheny.simpleclient.main.CsvWriter; +import org.polypheny.simpleclient.main.ProgressReporter; +import org.polypheny.simpleclient.query.QueryBuilder; +import org.polypheny.simpleclient.query.QueryListEntry; +import org.polypheny.simpleclient.query.RawQuery; +import org.polypheny.simpleclient.scenario.Scenario; +import org.polypheny.simpleclient.scenario.gavelNG.GavelNGProfile.QueryPossibility; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.ChangePasswordOfRandomUser; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.ChangeRandomAuction; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.CountAuction; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.CountBid; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.CountCategory; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.CountUser; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.InsertRandomAuction; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.InsertRandomBid; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.SearchAuction; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.SelectAllBidsOnRandomAuction; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.SelectDifferenceBetweenLowestAndHighestBid; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.SelectHighestBidOnRandomAuction; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.SelectHighestOverallBid; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.SelectMaxAmountConditionFinishedAuctions; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.SelectOtherInterestingActiveAuctions; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.SelectPriceBetweenAndNotInCategory; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.SelectRandomAuction; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.SelectRandomUser; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.SelectTheHundredNextEndingAuctionsOfRandomCategory; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.SelectTopHundredSellerByNumberOfAuctions; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.SelectTopTenCitiesByNumberOfCustomers; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.TruncateAuction; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.TruncateBid; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.TruncateCategory; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.TruncatePicture; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.TruncateUser; +import org.polypheny.simpleclient.scenario.multimedia.queryBuilder.CreateTable; + + +@Slf4j +public class GavelNG extends Scenario { + + private final GavelNGConfig config; + private final GavelNGProfile profile; + + private final List measuredTimes; + private final Map queryTypes; + private final Map> measuredTimePerQueryType; + + + public GavelNG( JdbcExecutor.ExecutorFactory jdbcExecutorFactory, PolyphenyDbMongoQlExecutor.ExecutorFactory mqlExecutorFactory, GavelNGConfig config, GavelNGProfile ngProfile, boolean commitAfterEveryQuery, boolean dumpQueryList, QueryMode queryMode ) { + super( jdbcExecutorFactory, mqlExecutorFactory, commitAfterEveryQuery, dumpQueryList, queryMode ); + this.config = config; + this.profile = ngProfile; + measuredTimes = Collections.synchronizedList( new LinkedList<>() ); + queryTypes = QueryPossibility.getQueryTypes(); + measuredTimePerQueryType = new ConcurrentHashMap<>(); + } + + + public Pair, QueryLanguage> getPossibleClasses( QueryPossibility query, Map numbers ) { + + final List insertQueries = Arrays.asList( + new InsertRandomAuction( numbers.get( "users" ), numbers.get( "categories" ), numbers.get( "categories" ), config ), + new InsertRandomBid( numbers.get( "auctions" ), numbers.get( "users" ) ) ); + final List updateQueries = Arrays.asList( + new ChangePasswordOfRandomUser( numbers.get( "users" ) ), + new ChangeRandomAuction( numbers.get( "auctions" ), config ) ); + final List simpleSelectQueries = Arrays.asList( + new SearchAuction( queryMode ), + new SelectAllBidsOnRandomAuction( numbers.get( "auctions" ), queryMode ), + new SelectHighestBidOnRandomAuction( numbers.get( "auctions" ), queryMode ), + new SelectHighestOverallBid( queryMode ), + new SelectPriceBetweenAndNotInCategory( queryMode ), + new SelectRandomAuction( numbers.get( "auctions" ), queryMode ), + new SelectRandomUser( numbers.get( "users" ), queryMode ) ); + final List complexSelectQueries = Arrays.asList( + new SelectTheHundredNextEndingAuctionsOfRandomCategory( numbers.get( "categories" ), config, queryMode ), + new SelectTopHundredSellerByNumberOfAuctions( queryMode ), + new SelectTopTenCitiesByNumberOfCustomers( queryMode ), + new SelectMaxAmountConditionFinishedAuctions( queryMode ), + new SelectDifferenceBetweenLowestAndHighestBid( queryMode ), + new SelectOtherInterestingActiveAuctions( queryMode ) ); + final List truncateQueries = Arrays.asList( + new TruncateAuction(), + new TruncateBid(), + new TruncateCategory(), + new TruncatePicture(), + new TruncateUser() + + ); + final List deleteQueries = Arrays.asList( + + ); + + switch ( query ) { + case INSERT_SQL: + return new Pair<>( insertQueries, QueryLanguage.SQL ); + case INSERT_MQL: + return new Pair<>( insertQueries, QueryLanguage.MQL ); + case UPDATE_SQL: + return new Pair<>( updateQueries, QueryLanguage.SQL ); + case UPDATE_MQL: + return new Pair<>( updateQueries, QueryLanguage.MQL ); + case SIMPLE_SELECT_SQL: + return new Pair<>( simpleSelectQueries, QueryLanguage.SQL ); + case SIMPLE_SELECT_MQL: + return new Pair<>( simpleSelectQueries, QueryLanguage.MQL ); + case COMPLEX_SELECT_SQL: + return new Pair<>( complexSelectQueries, QueryLanguage.SQL ); + case COMPLEX_SELECT_MQL: + return new Pair<>( complexSelectQueries, QueryLanguage.MQL ); + case TRUNCATE_SQL: + return new Pair<>( truncateQueries, QueryLanguage.SQL ); + case TRUNCATE_MQL: + return new Pair<>( truncateQueries, QueryLanguage.MQL ); + case DELETE_SQL: + return new Pair<>( deleteQueries, QueryLanguage.SQL ); + case DELETE_MQL: + return new Pair<>( deleteQueries, QueryLanguage.MQL ); + + default: + throw new RuntimeException( "This QueryPossibility has no saved Queries. Please add a List of Classes with suitable queries." ); + } + } + + + @Override + public long execute( ProgressReporter progressReporter, CsvWriter csvWriter, File outputDirectory, int numberOfThreads ) { + + log.info( "Analyzing currently stored data..." ); + Map numbers = getNumbers(); + InsertRandomAuction.setNextId( numbers.get( "auctions" ) + 1 ); + InsertRandomBid.setNextId( numbers.get( "bids" ) + 1 ); + + log.info( "Preparing query list for the benchmark..." ); + List queryList = new Vector<>(); + + for ( Pair, Integer> part : profile.timeline ) { + Pair queryInfo = part.left; + QueryPossibility query = queryInfo.left; + Pair, QueryLanguage> possibleQueries = getPossibleClasses( query, numbers ); + if ( possibleQueries.left.size() > 0 ) { + Random rand = new Random(); + rand.setSeed( 1234 ); + for ( int i = 0; i < queryInfo.right; i++ ) { + measuredTimePerQueryType.put( query.id, Collections.synchronizedList( new LinkedList<>() ) ); + queryList.add( new QueryListEntry( possibleQueries.left.get( rand.nextInt( possibleQueries.left.size() ) ).getNewQuery(), query.id, part.right, possibleQueries.right ) ); + } + } + } + + // This dumps the sql queries independent of the selected interface + if ( outputDirectory != null && dumpQueryList ) { + log.info( "Dump query list..." ); + try { + FileWriter fw = new FileWriter( outputDirectory.getPath() + File.separator + "queryList" ); + queryList.forEach( query -> { + try { + if ( query.queryLanguage == QueryLanguage.SQL ) { + fw.append( query.query.getSql() ).append( "\n" ); + } else if ( query.queryLanguage == QueryLanguage.MQL ) { + fw.append( query.query.getMongoQl() ).append( "\n" ); + } else { + throw new RuntimeException( "Querylanguag is not implemented yet." ); + } + } catch ( IOException e ) { + log.error( "Error while dumping query list", e ); + } + } ); + fw.close(); + } catch ( IOException e ) { + log.error( "Error while dumping query list", e ); + } + } + + log.info( "Executing benchmark..." ); + (new Thread( new ProgressReporter.ReportQueryListProgress( queryList, progressReporter ) )).start(); + long startTime = System.nanoTime(); + + ArrayList threads = new ArrayList<>(); + + for ( int i = 0; i < numberOfThreads; i++ ) { + threads.add( new EvaluationThread( queryList, executorFactory.createExecutorInstance( csvWriter ), mqlExecutorFactory.createExecutorInstance( csvWriter ) ) ); + } + + EvaluationThreadMonitor threadMonitor = new EvaluationThreadMonitor( threads ); + threads.forEach( t -> t.setThreadMonitor( threadMonitor ) ); + + for ( EvaluationThread thread : threads ) { + thread.start(); + } + + for ( Thread thread : threads ) { + try { + thread.join(); + } catch ( InterruptedException e ) { + throw new RuntimeException( "Unexpected interrupt", e ); + } + } + + long runTime = System.nanoTime() - startTime; + + for ( EvaluationThread thread : threads ) { + thread.closeExecutor(); + } + + if ( threadMonitor.aborted ) { + throw new RuntimeException( "Exception while executing benchmark", threadMonitor.exception ); + } + + log.info( "run time: {} s", runTime / 1000000000 ); + + return runTime; + } + + + @Override + public void warmUp( ProgressReporter progressReporter ) { + log.info( "Analyzing currently stored data..." ); + Map numbers = getNumbers(); + + InsertRandomAuction.setNextId( numbers.get( "auctions" ) + 2 ); + InsertRandomBid.setNextId( numbers.get( "bids" ) + 2 ); + + log.info( "Warm-up..." ); + Executor jdbcExecutorFactory = null; + Executor mqlExecutorFactory = null; + for ( int i = 0; i < config.numberOfWarmUpIterations; i++ ) { + try { + jdbcExecutorFactory = executorFactory.createExecutorInstance(); + mqlExecutorFactory = this.mqlExecutorFactory.createExecutorInstance(); + + for ( QueryPossibility query : profile.warmUp ) { + Pair, QueryLanguage> possibleQueries = getPossibleClasses( query, numbers ); + if ( possibleQueries.left.size() > 0 ) { + for ( QueryBuilder queryBuilder : possibleQueries.left ) { + if ( possibleQueries.right == QueryLanguage.SQL ) { + jdbcExecutorFactory.executeQuery( queryBuilder.getNewQuery() ); + } else if ( possibleQueries.right == QueryLanguage.MQL ) { + mqlExecutorFactory.executeQuery( queryBuilder.getNewQuery() ); + } + } + } + } + + } catch ( ExecutorException e ) { + throw new RuntimeException( "Error while executing warm-up queries", e ); + } finally { + commitAndCloseExecutor( jdbcExecutorFactory ); + commitAndCloseExecutor( mqlExecutorFactory ); + } + try { + Thread.sleep( 10000 ); + } catch ( InterruptedException e ) { + throw new RuntimeException( "Unexpected interrupt", e ); + } + } + } + + + private class EvaluationThread extends Thread { + + private final Executor jdbcExecutorFactory; + private final Executor mqlExecutorFactory; + private final List theQueryList; + private boolean abort = false; + @Setter + private EvaluationThreadMonitor threadMonitor; + + + EvaluationThread( List queryList, Executor jdbcExecutorFactory, Executor mqlExecutorFactory ) { + super( "EvaluationThread" ); + this.jdbcExecutorFactory = jdbcExecutorFactory; + this.mqlExecutorFactory = mqlExecutorFactory; + theQueryList = queryList; + } + + + @Override + public void run() { + long measuredTimeStart; + long measuredTime; + QueryListEntry queryListEntry; + + while ( !theQueryList.isEmpty() && !abort ) { + measuredTimeStart = System.nanoTime(); + try { + queryListEntry = theQueryList.remove( 0 ); + } catch ( IndexOutOfBoundsException e ) { // This is neither nice nor efficient... + // This can happen due to concurrency if two threads enter the while-loop and there is only one thread left + // Simply leaf the loop + break; + } + try { + if ( queryListEntry.queryLanguage == QueryLanguage.SQL ) { + jdbcExecutorFactory.executeQuery( queryListEntry.query ); + } else if ( queryListEntry.queryLanguage == QueryLanguage.MQL ) { + mqlExecutorFactory.executeQuery( queryListEntry.query ); + } else { + throw new RuntimeException( "Query language is not implemented yet." ); + } + } catch ( ExecutorException e ) { + log.error( "Caught exception while executing the following query: {}", queryListEntry.query.getClass().getName(), e ); + threadMonitor.notifyAboutError( e ); + try { + if ( queryListEntry.queryLanguage == QueryLanguage.SQL ) { + jdbcExecutorFactory.executeRollback(); + } else if ( queryListEntry.queryLanguage == QueryLanguage.MQL ) { + mqlExecutorFactory.executeRollback(); + } else { + throw new RuntimeException( "Not possible to rollback, the query language is not supported." ); + } + } catch ( ExecutorException ex ) { + log.error( "Error while rollback", e ); + } + throw new RuntimeException( e ); + } + measuredTime = System.nanoTime() - measuredTimeStart; + measuredTimes.add( measuredTime ); + measuredTimePerQueryType.get( queryListEntry.templateId ).add( measuredTime ); + + try { + Thread.sleep( queryListEntry.delay ); + } catch ( InterruptedException e ) { + e.printStackTrace(); + } + + if ( commitAfterEveryQuery ) { + try { + if ( queryListEntry.queryLanguage == QueryLanguage.SQL ) { + jdbcExecutorFactory.executeCommit(); + } else if ( queryListEntry.queryLanguage == QueryLanguage.MQL ) { + mqlExecutorFactory.executeCommit(); + } else { + throw new RuntimeException( "Not possible to commit, the query language is not supported." ); + } + } catch ( ExecutorException e ) { + log.error( "Caught exception while committing", e ); + threadMonitor.notifyAboutError( e ); + try { + if ( queryListEntry.queryLanguage == QueryLanguage.SQL ) { + jdbcExecutorFactory.executeRollback(); + } else if ( queryListEntry.queryLanguage == QueryLanguage.MQL ) { + mqlExecutorFactory.executeRollback(); + } else { + throw new RuntimeException( "Not possible to rollback, the query language is not supported." ); + } + } catch ( ExecutorException ex ) { + log.error( "Error while rollback", e ); + } + throw new RuntimeException( e ); + } + } + } + + try { + jdbcExecutorFactory.executeCommit(); + mqlExecutorFactory.executeCommit(); + } catch ( ExecutorException e ) { + log.error( "Caught exception while committing", e ); + threadMonitor.notifyAboutError( e ); + try { + jdbcExecutorFactory.executeRollback(); + mqlExecutorFactory.executeRollback(); + } catch ( ExecutorException ex ) { + log.error( "Error while rollback", e ); + } + throw new RuntimeException( e ); + } + jdbcExecutorFactory.flushCsvWriter(); + mqlExecutorFactory.flushCsvWriter(); + } + + + public void abort() { + this.abort = true; + } + + + public void closeExecutor() { + commitAndCloseExecutor( jdbcExecutorFactory ); + commitAndCloseExecutor( mqlExecutorFactory ); + } + + } + + + private class EvaluationThreadMonitor { + + private final List threads; + @Getter + private Exception exception; + @Getter + private boolean aborted; + + + public EvaluationThreadMonitor( List threads ) { + this.threads = threads; + this.aborted = false; + } + + + public void abortAll() { + this.aborted = true; + threads.forEach( EvaluationThread::abort ); + } + + + public void notifyAboutError( Exception e ) { + exception = e; + abortAll(); + } + + } + + + private long countNumberOfRecords( Executor executor, QueryBuilder queryBuilder ) throws ExecutorException { + return executor.executeQueryAndGetNumber( queryBuilder.getNewQuery() ); + } + + + @Override + public void createSchema( DatabaseInstance databaseInstance, boolean includingKeys ) { + log.info( "Creating schema..." ); + InputStream file; + + PolyphenyDbExecutor executor = (PolyphenyDbExecutor) executorFactory.createExecutorInstance(); + + file = ClassLoader.getSystemResourceAsStream( "org/polypheny/simpleclient/scenario/gavelNG/schema.sql" ); + executeSchema( file, profile, executor.getDataStoreNames() ); + + file = ClassLoader.getSystemResourceAsStream( "org/polypheny/simpleclient/scenario/gavelNG/schema.mongoql" ); + executeMongoQlSchema( file, profile, executor.getDataStoreNames() ); + + // Create Views / Materialized Views + if ( queryMode == QueryMode.VIEW ) { + log.info( "Creating Views ..." ); + file = ClassLoader.getSystemResourceAsStream( "org/polypheny/simpleclient/scenario/gavel/view.sql" ); + executeSchema( file, profile, executor.getDataStoreNames() ); + } else if ( queryMode == QueryMode.MATERIALIZED ) { + log.info( "Creating Materialized Views ..." ); + file = ClassLoader.getSystemResourceAsStream( "org/polypheny/simpleclient/scenario/gavel/materialized.sql" ); + executeSchema( file, profile, executor.getDataStoreNames() ); + } + } + + + private void executeMongoQlSchema( InputStream file, GavelNGProfile gavelNGSettings, Map> dataStoreNames ) { + Executor executor = null; + if ( file == null ) { + throw new RuntimeException( "Unable to load schema definition file" ); + } + try ( BufferedReader bf = new BufferedReader( new InputStreamReader( file ) ) ) { + executor = mqlExecutorFactory.createExecutorInstance(); + String line = bf.readLine(); + executor.executeQuery( new RawQuery( null, null, "use test", null, false ) ); + while ( line != null ) { + if ( !gavelNGSettings.tableStores.isEmpty() ) { + List> tableStores = gavelNGSettings.tableStores; + for ( Pair tableStore : tableStores ) { + if ( line.replace( "\"", "" ).equals( tableStore.left ) ) { + line = line + ",{\"store\":\"" + dataStoreNames.get( tableStore.right ).get( dataStoreNames.get( tableStore.right ).size() - 1 ) + "\"}"; + } + } + } + executor.executeQuery( new RawQuery( null, null, "db.createCollection(" + line + ")", null, false ) ); + line = bf.readLine(); + } + } catch ( IOException | ExecutorException e ) { + throw new RuntimeException( "Exception while creating schema", e ); + } finally { + commitAndCloseExecutor( executor ); + } + } + + + private void executeSchema( InputStream file, GavelNGProfile gavelNGSettings, Map> dataStoreNames ) { + Executor executor = null; + if ( file == null ) { + throw new RuntimeException( "Unable to load schema definition file" ); + } + try ( BufferedReader bf = new BufferedReader( new InputStreamReader( file ) ) ) { + executor = executorFactory.createExecutorInstance(); + String line = bf.readLine(); + while ( line != null ) { + if ( !gavelNGSettings.tableStores.isEmpty() ) { + List> tableStores = gavelNGSettings.tableStores; + for ( Pair tableStore : tableStores ) { + if ( line.startsWith( "CREATE" ) && line.split( " " )[2].replace( "\"", "" ).equals( tableStore.left ) ) { + line = line + " ON STORE \"" + dataStoreNames.get( tableStore.right ).get( dataStoreNames.get( tableStore.right ).size() - 1 ) + "\""; + } + } + } + executor.executeQuery( new RawQuery( line, null, false ) ); + line = bf.readLine(); + } + } catch ( IOException | ExecutorException e ) { + throw new RuntimeException( "Exception while creating schema", e ); + } finally { + commitAndCloseExecutor( executor ); + } + } + + + @Override + public void generateData( DatabaseInstance databaseInstance, ProgressReporter progressReporter ) { + log.info( "Generating data..." ); + + DataGenerationThreadMonitor threadMonitor = new DataGenerationThreadMonitor(); + + Executor executor1 = executorFactory.createExecutorInstance(); + Executor executor1Mongo = mqlExecutorFactory.createExecutorInstance(); + DataGeneratorGavelNG dataGeneratorGavelNG = new DataGeneratorGavelNG( executor1, executor1Mongo, config, progressReporter, threadMonitor ); + List queryLanguages = Arrays.asList( QueryLanguage.SQL, QueryLanguage.MQL ); + + try { + for ( QueryLanguage queryLanguage : queryLanguages ) { + dataGeneratorGavelNG.truncateTables( queryLanguage ); + dataGeneratorGavelNG.generateCategories( queryLanguage ); + dataGeneratorGavelNG.generateConditions( queryLanguage ); + } + + } catch ( ExecutorException e ) { + throw new RuntimeException( "Exception while generating data", e ); + } finally { + commitAndCloseExecutor( executor1Mongo ); + commitAndCloseExecutor( executor1 ); + } + + ArrayList threads = new ArrayList<>(); + int numberOfUserGenerationThreads; + if ( executorFactory.getMaxNumberOfThreads() > 0 && config.numberOfUserGenerationThreads > executorFactory.getMaxNumberOfThreads() ) { + numberOfUserGenerationThreads = executorFactory.getMaxNumberOfThreads(); + log.warn( "Limiting number of executor threads to {} threads (instead of {} as specified by the job)", numberOfUserGenerationThreads, config.numberOfUserGenerationThreads ); + } else { + numberOfUserGenerationThreads = config.numberOfUserGenerationThreads; + } + for ( int i = 0; i < numberOfUserGenerationThreads; i++ ) { + Runnable task = () -> { + Executor jdbcExecutorFactory = executorFactory.createExecutorInstance(); + Executor mqlExecutorFactory = this.mqlExecutorFactory.createExecutorInstance(); + try { + DataGeneratorGavelNG dg = new DataGeneratorGavelNG( jdbcExecutorFactory, mqlExecutorFactory, config, progressReporter, threadMonitor ); + for ( QueryLanguage queryLanguage : queryLanguages ) { + dg.generateUsers( config.numberOfUsers / numberOfUserGenerationThreads, queryLanguage ); + } + } catch ( ExecutorException e ) { + threadMonitor.notifyAboutError( e ); + try { + jdbcExecutorFactory.executeRollback(); + mqlExecutorFactory.executeRollback(); + } catch ( ExecutorException ex ) { + log.error( "Error while rollback", e ); + } + log.error( "Exception while generating data", e ); + } finally { + try { + jdbcExecutorFactory.closeConnection(); + mqlExecutorFactory.closeConnection(); + } catch ( ExecutorException e ) { + log.error( "Error while closing connection", e ); + } + } + }; + Thread thread = new Thread( task ); + threads.add( thread ); + thread.start(); + } + + if ( !config.parallelizeUserGenerationAndAuctionGeneration ) { + for ( Thread t : threads ) { + try { + t.join(); + } catch ( InterruptedException e ) { + throw new RuntimeException( "Unexpected interrupt", e ); + } + } + } + + int numberOfAuctionGenerationThreads = config.numberOfAuctionGenerationThreads; + if ( executorFactory.getMaxNumberOfThreads() > 0 && config.numberOfAuctionGenerationThreads > executorFactory.getMaxNumberOfThreads() ) { + numberOfAuctionGenerationThreads = executorFactory.getMaxNumberOfThreads(); + log.warn( "Limiting number of auction generation threads to {} threads (instead of {} as specified by the job)", numberOfAuctionGenerationThreads, config.numberOfAuctionGenerationThreads ); + } + int rangeSize = config.numberOfAuctions / numberOfAuctionGenerationThreads; + for ( int i = 1; i <= numberOfAuctionGenerationThreads; i++ ) { + final int start = ((i - 1) * rangeSize) + 1; + final int end = rangeSize * i; + Runnable task = () -> { + Executor jdbcExecutorFactory = executorFactory.createExecutorInstance(); + Executor mqlExecutorFactory = this.mqlExecutorFactory.createExecutorInstance(); + try { + DataGeneratorGavelNG dg = new DataGeneratorGavelNG( jdbcExecutorFactory, mqlExecutorFactory, config, progressReporter, threadMonitor ); + for ( QueryLanguage queryLanguage : queryLanguages ) { + dg.generateAuctions( start, end, queryLanguage ); + } + + } catch ( ExecutorException e ) { + threadMonitor.notifyAboutError( e ); + try { + jdbcExecutorFactory.executeRollback(); + mqlExecutorFactory.executeRollback(); + } catch ( ExecutorException ex ) { + log.error( "Error while rollback", e ); + } + log.error( "Exception while generating data", e ); + } finally { + try { + jdbcExecutorFactory.closeConnection(); + mqlExecutorFactory.closeConnection(); + } catch ( ExecutorException e ) { + log.error( "Error while closing connection", e ); + } + } + }; + Thread thread = new Thread( task ); + threads.add( thread ); + thread.start(); + } + + for ( Thread t : threads ) { + try { + t.join(); + } catch ( InterruptedException e ) { + throw new RuntimeException( "Unexpected interrupt", e ); + } + } + + if ( queryMode == QueryMode.MATERIALIZED ) { + updateMaterializedView(); + } + + if ( threadMonitor.aborted ) { + throw new RuntimeException( "Exception while generating data", threadMonitor.exception ); + } + } + + + public void updateMaterializedView() { + log.info( "Update Materialized View..." ); + Executor executor = null; + try { + executor = executorFactory.createExecutorInstance(); + executor.executeQuery( (new CreateTable( "ALTER MATERIALIZED VIEW user_materialized FRESHNESS MANUAL" )).getNewQuery() ); + executor.executeQuery( (new CreateTable( "ALTER MATERIALIZED VIEW bid_materialized FRESHNESS MANUAL" )).getNewQuery() ); + executor.executeQuery( (new CreateTable( "ALTER MATERIALIZED VIEW picture_materialized FRESHNESS MANUAL" )).getNewQuery() ); + executor.executeQuery( (new CreateTable( "ALTER MATERIALIZED VIEW auction_materialized FRESHNESS MANUAL" )).getNewQuery() ); + executor.executeQuery( (new CreateTable( "ALTER MATERIALIZED VIEW category_materialized FRESHNESS MANUAL" )).getNewQuery() ); + executor.executeQuery( (new CreateTable( "ALTER MATERIALIZED VIEW countAuction_materialized FRESHNESS MANUAL" )).getNewQuery() ); + executor.executeQuery( (new CreateTable( "ALTER MATERIALIZED VIEW countBid_materialized FRESHNESS MANUAL" )).getNewQuery() ); + executor.executeQuery( (new CreateTable( "ALTER MATERIALIZED VIEW auctionCategory_materialized FRESHNESS MANUAL" )).getNewQuery() ); + executor.executeQuery( (new CreateTable( "ALTER MATERIALIZED VIEW topHundredSellerByNumberOfAuctions_materialized FRESHNESS MANUAL" )).getNewQuery() ); + executor.executeQuery( (new CreateTable( "ALTER MATERIALIZED VIEW highestBid_materialized FRESHNESS MANUAL" )).getNewQuery() ); + executor.executeQuery( (new CreateTable( "ALTER MATERIALIZED VIEW priceBetween_materialized FRESHNESS MANUAL" )).getNewQuery() ); + } catch ( ExecutorException e ) { + throw new RuntimeException( "Exception while updating Materialized View", e ); + } finally { + commitAndCloseExecutor( executor ); + } + } + + + static class DataGenerationThreadMonitor { + + private final List dataGeneratorGavelNGS; + @Getter + private boolean aborted; + @Getter + private Exception exception = null; + + + DataGenerationThreadMonitor() { + this.dataGeneratorGavelNGS = new LinkedList<>(); + aborted = false; + } + + + void registerDataGenerator( DataGeneratorGavelNG instance ) { + dataGeneratorGavelNGS.add( instance ); + } + + + public void abortAll() { + this.aborted = true; + dataGeneratorGavelNGS.forEach( DataGeneratorGavelNG::abort ); + } + + + public void notifyAboutError( Exception e ) { + exception = e; + abortAll(); + } + + } + + + @Override + public void analyze( Properties properties, File outputDirectory ) { + properties.put( "measuredTime", calculateMean( measuredTimes ) ); + + measuredTimePerQueryType.forEach( ( templateId, time ) -> { + properties.put( "queryTypes_" + QueryPossibility.getById( templateId ) + "_mean", calculateMean( time ) ); + if ( ChronosAgent.STORE_INDIVIDUAL_QUERY_TIMES ) { + properties.put( "queryTypes_" + QueryPossibility.getById( templateId ) + "_all", Joiner.on( ',' ).join( time ) ); + } + properties.put( "queryTypes_" + QueryPossibility.getById( templateId ) + "_example", queryTypes.get( templateId ) ); + } ); + properties.put( "queryTypes_maxId", queryTypes.size() ); + } + + + @Override + public int getNumberOfInsertThreads() { + return config.numberOfUserGenerationThreads + config.numberOfAuctionGenerationThreads; + } + + + private Map getNumbers() { + Map numbers = new HashMap<>(); + Executor executor = null; + try { + executor = executorFactory.createExecutorInstance(); + numbers.put( "auctions", (int) countNumberOfRecords( executor, new CountAuction( QueryMode.TABLE ) ) ); + numbers.put( "users", (int) countNumberOfRecords( executor, new CountUser() ) ); + numbers.put( "categories", (int) countNumberOfRecords( executor, new CountCategory() ) ); + numbers.put( "bids", (int) countNumberOfRecords( executor, new CountBid( QueryMode.TABLE ) ) ); + + log.debug( "Number of auctions: " + numbers.get( "auctions" ) ); + log.debug( "Number of users: " + numbers.get( "users" ) ); + log.debug( "Number of categories: " + numbers.get( "categories" ) ); + log.debug( "Number of bids: " + numbers.get( "bids" ) ); + } catch ( ExecutorException e ) { + throw new RuntimeException( "Exception while analyzing currently stored data: " + e.getMessage(), e ); + } finally { + commitAndCloseExecutor( executor ); + } + log.info( "Current number of elements in the database:\nAuctions: {} | Users: {} | Categories: {} | Bids: {}", numbers.get( "auction" ), numbers.get( "user" ), numbers.get( "categories" ), numbers.get( "bids" ) ); + return numbers; + } + + + public void commitAndCloseExecutor( Executor executor ) { + if ( executor != null ) { + try { + executor.executeCommit(); + } catch ( ExecutorException e ) { + try { + executor.executeRollback(); + } catch ( ExecutorException ex ) { + log.error( "Error while rollback connection", e ); + } + } + try { + executor.closeConnection(); + } catch ( ExecutorException e ) { + log.error( "Error while closing connection", e ); + } + } + } + + + public enum QueryLanguage { + SQL, MQL + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/GavelNGConfig.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/GavelNGConfig.java new file mode 100644 index 00000000..78010563 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/GavelNGConfig.java @@ -0,0 +1,133 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG; + + +import java.util.Arrays; +import java.util.Map; +import java.util.Properties; +import lombok.extern.slf4j.Slf4j; +import org.polypheny.simpleclient.scenario.AbstractConfig; + + +@Slf4j +public class GavelNGConfig extends AbstractConfig { + + public final int numberOfUsers; + public final int numberOfAuctions; + public final int numberOfCategories; + public final int numberOfConditions; + public final int auctionTitleMinLength; + public final int auctionTitleMaxLength; + public final int auctionDescriptionMinLength; + public final int auctionDescriptionMaxLength; + public final int auctionDateMaxYearsInPast; + public final int auctionNumberOfDays; + public final int minNumberOfBidsPerAuction; + public final int maxNumberOfBidsPerAuction; + public final int minNumberOfPicturesPerAuction; + public final int maxNumberOfPicturesPerAuction; + + public final int maxBatchSize; + public final boolean usePreparedBatchForDataInsertion; + + public final int numberOfUserGenerationThreads; + public final int numberOfAuctionGenerationThreads; + public final boolean parallelizeUserGenerationAndAuctionGeneration; + + + public GavelNGConfig( Properties properties, int multiplier ) { + super( "gavel", "polypheny", properties ); + + numberOfUsers = getIntProperty( properties, "numberOfUsers" ) * multiplier; + numberOfAuctions = getIntProperty( properties, "numberOfAuctions" ) * multiplier; + numberOfCategories = getIntProperty( properties, "numberOfCategories" ); + numberOfConditions = getIntProperty( properties, "numberOfConditions" ); + auctionTitleMinLength = getIntProperty( properties, "auctionTitleMinLength" ); + auctionTitleMaxLength = getIntProperty( properties, "auctionTitleMaxLength" ); + auctionDescriptionMinLength = getIntProperty( properties, "auctionDescriptionMinLength" ); + auctionDescriptionMaxLength = getIntProperty( properties, "auctionDescriptionMaxLength" ); + auctionDateMaxYearsInPast = getIntProperty( properties, "auctionDateMaxYearsInPast" ); + auctionNumberOfDays = getIntProperty( properties, "auctionNumberOfDays" ); + minNumberOfBidsPerAuction = getIntProperty( properties, "minNumberOfBidsPerAuction" ); + maxNumberOfBidsPerAuction = getIntProperty( properties, "maxNumberOfBidsPerAuction" ) * multiplier; + minNumberOfPicturesPerAuction = getIntProperty( properties, "minNumberOfPicturesPerAuction" ); + maxNumberOfPicturesPerAuction = getIntProperty( properties, "maxNumberOfPicturesPerAuction" ) * multiplier; + + maxBatchSize = getIntProperty( properties, "maxBatchSize" ); + usePreparedBatchForDataInsertion = getBooleanProperty( properties, "usePreparedBatchForDataInsertion" ); + + numberOfUserGenerationThreads = getIntProperty( properties, "numberOfUserGenerationThreads" ); + numberOfAuctionGenerationThreads = getIntProperty( properties, "numberOfAuctionGenerationThreads" ); + parallelizeUserGenerationAndAuctionGeneration = getBooleanProperty( properties, "parallelizeUserGenerationAndAuctionGeneration" ); + } + + + public GavelNGConfig( Map cdl ) { + super( "gavelng", cdl.get( "store" ), cdl ); + + + // Data Generation + numberOfUsers = Integer.parseInt( cdl.get( "numberOfUsers" ) ); + numberOfAuctions = Integer.parseInt( cdl.get( "numberOfAuctions" ) ); + numberOfCategories = Integer.parseInt( cdl.get( "numberOfCategories" ) ); + numberOfConditions = Integer.parseInt( cdl.get( "numberOfConditions" ) ); + auctionTitleMinLength = Integer.parseInt( cdl.get( "auctionTitleMinLength" ) ); + auctionTitleMaxLength = Integer.parseInt( cdl.get( "auctionTitleMaxLength" ) ); + auctionDescriptionMinLength = Integer.parseInt( cdl.get( "auctionDescriptionMinLength" ) ); + auctionDescriptionMaxLength = Integer.parseInt( cdl.get( "auctionDescriptionMaxLength" ) ); + auctionDateMaxYearsInPast = Integer.parseInt( cdl.get( "auctionDateMaxYearsInPast" ) ); + auctionNumberOfDays = Integer.parseInt( cdl.get( "auctionNumberOfDays" ) ); + minNumberOfBidsPerAuction = Integer.parseInt( cdl.get( "minNumberOfBidsPerAuction" ) ); + maxNumberOfBidsPerAuction = Integer.parseInt( cdl.get( "maxNumberOfBidsPerAuction" ) ); + minNumberOfPicturesPerAuction = Integer.parseInt( cdl.get( "minNumberOfPicturesPerAuction" ) ); + maxNumberOfPicturesPerAuction = Integer.parseInt( cdl.get( "maxNumberOfPicturesPerAuction" ) ); + + maxBatchSize = Integer.parseInt( cdl.get( "maxBatchSize" ) ); + usePreparedBatchForDataInsertion = true; + + numberOfUserGenerationThreads = Integer.parseInt( cdl.get( "numberOfUserGenerationThreads" ) ); + numberOfAuctionGenerationThreads = Integer.parseInt( cdl.get( "numberOfAuctionGenerationThreads" ) ); + + parallelizeUserGenerationAndAuctionGeneration = Boolean.parseBoolean( cdl.get( "parallelizeUserGenerationAndAuctionGeneration" ) ); + + + // Policy Settings + storePolicies.addAll( Arrays.asList( cdl.get( "storePolicy" ).split( "," ) ) ); + selfAdaptingPolicies.addAll( Arrays.asList( cdl.get( "selfAdaptingPolicy" ).split( "," ) ) ); + multipleDataStores.addAll( Arrays.asList( cdl.get( "multipleDataStores" ).split( "," ) ) ); + usePolicies = cdl.get( "policySelfAdaptiveness" ); + statisticActiveTracking = Boolean.parseBoolean( cdl.get( "statisticActiveTracking" ) ); + + } + + + @Override + public boolean usePreparedBatchForDataInsertion() { + return this.usePreparedBatchForDataInsertion; + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/GavelNGProfile.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/GavelNGProfile.java new file mode 100644 index 00000000..5f109563 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/GavelNGProfile.java @@ -0,0 +1,212 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Queue; +import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; + + +@Slf4j +public class GavelNGProfile { + + public final Queue, Integer>> timeline; + public final Queue warmUp; + public final List> tableStores = new ArrayList<>(); + public final List> factoryStores = new ArrayList<>(); + + + public GavelNGProfile( Properties properties ) { + timeline = castProfileTimeline( properties.getProperty( "schedules" ) ); + warmUp = castWarmUp( properties.getProperty( "warmup" ) ); + selectStore( properties.getProperty( "storeForFactory" ), properties.getProperty( "storeForTable" ) ); + } + + + public GavelNGProfile( Map cdl ) { + timeline = castProfileTimeline( cdl.get( "schedules" ) ); + warmUp = castWarmUp( cdl.get( "warmup" ) ); + selectStore( cdl.get( "storeForFactory" ), cdl.get( "storeForTable" ) ); + } + + + private void selectStore( String storeForFactory, String storeForTable ) { + if ( !Objects.equals( storeForTable, "" ) ) { + String[] selectedStores = storeForTable.replace( "\"", "" ).split( "," ); + for ( String selectedStore : selectedStores ) { + tableStores.add( new Pair<>( selectedStore.split( "-" )[0], selectedStore.split( "-" )[1] ) ); + } + } else if ( !Objects.equals( storeForFactory, "" ) ) { + String[] selectedStores = storeForFactory.replace( "\"", "" ).split( "," ); + for ( String selectedStore : selectedStores ) { + factoryStores.add( new Pair<>( selectedStore.split( "-" )[0], selectedStore.split( "-" )[1] ) ); + } + } else { + log.warn( "No particular Store selected for the table creation." ); + } + } + + + private Queue castWarmUp( String warmup ) { + Queue warmUp = new LinkedList<>(); + String[] parts = warmup.replace( "\"", "" ).split( "," ); + + for ( String part : parts ) { + QueryPossibility query = getQueryPossibility( part ); + warmUp.add( query ); + } + return warmUp; + } + + + private Queue, Integer>> castProfileTimeline( String profileTimeline ) { + Queue, Integer>> castedTimeline = new LinkedList<>(); + + String[] parts = profileTimeline.replace( "\"", "" ).split( "," ); + + for ( String part : parts ) { + + QueryPossibility query = getQueryPossibility( part ); + + String withoutLanguage = part.split( "-" )[1]; + castedTimeline.add( new Pair<>( new Pair<>( query, Integer.parseInt( withoutLanguage.split( "d" )[0].substring( 1 ) ) ), Integer.parseInt( withoutLanguage.split( "d" )[1] ) ) ); + } + + return castedTimeline; + } + + + @NotNull + private QueryPossibility getQueryPossibility( String part ) { + QueryPossibility query; + + if ( part.startsWith( "sql-" ) ) { + switch ( part.split( "-" )[1].substring( 0, 1 ) ) { + case "i": + query = QueryPossibility.INSERT_SQL; + break; + case "s": + query = QueryPossibility.SIMPLE_SELECT_SQL; + break; + case "c": + query = QueryPossibility.COMPLEX_SELECT_SQL; + break; + case "u": + query = QueryPossibility.UPDATE_SQL; + break; + case "d": + query = QueryPossibility.DELETE_SQL; + break; + case "t": + query = QueryPossibility.TRUNCATE_SQL; + break; + default: + log.warn( "Please check how to write a Scenario, this letter is not possible to use." ); + throw new RuntimeException( "Please check how to write a Scenario, this letter is not possible to use." ); + } + + } else if ( part.startsWith( "mql-" ) ) { + switch ( part.split( "-" )[1].substring( 0, 1 ) ) { + case "i": + query = QueryPossibility.INSERT_MQL; + break; + case "s": + query = QueryPossibility.SIMPLE_SELECT_MQL; + break; + case "c": + query = QueryPossibility.COMPLEX_SELECT_MQL; + break; + case "u": + query = QueryPossibility.UPDATE_MQL; + break; + case "d": + query = QueryPossibility.DELETE_MQL; + break; + case "t": + query = QueryPossibility.TRUNCATE_MQL; + break; + default: + log.warn( "Please check how to write a Scenario, this letter is not possible to use." ); + throw new RuntimeException( "Please check how to write a Scenario, this letter is not possible to use." ); + } + } else { + log.warn( "Only possible to use MQL or SQL." ); + throw new RuntimeException( "Only possible to use MQL or SQL." ); + } + return query; + } + + + enum QueryPossibility { + INSERT_SQL( 1 ), + SIMPLE_SELECT_SQL( 2 ), + COMPLEX_SELECT_SQL( 3 ), + UPDATE_SQL( 4 ), + DELETE_SQL( 5 ), + TRUNCATE_SQL( 6 ), + INSERT_MQL( 7 ), + SIMPLE_SELECT_MQL( 8 ), + COMPLEX_SELECT_MQL( 9 ), + UPDATE_MQL( 10 ), + DELETE_MQL( 11 ), + TRUNCATE_MQL( 12 ); + + + public int id; + + + QueryPossibility( int id ) { + this.id = id; + } + + + public static Map getQueryTypes() { + Map queryTypes = new HashMap<>(); + for ( QueryPossibility queryPossibility : values() ) { + queryTypes.put( queryPossibility.id, queryPossibility.name() ); + } + return queryTypes; + } + + + public static String getById( Integer templateId ) { + for ( QueryPossibility queryPossibility : values() ) { + if ( queryPossibility.id == templateId ) { + return queryPossibility.name(); + } + } + return "unknown"; + } + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/Pair.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/Pair.java new file mode 100644 index 00000000..fc3fe06b --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/Pair.java @@ -0,0 +1,107 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG; + +import java.util.Map; +import java.util.Objects; +import org.jetbrains.annotations.NotNull; + +public class Pair implements Comparable>, Map.Entry { + + + public final T1 left; + public final T2 right; + + + /** + * Creates a Pair. + * + * @param left left value + * @param right right value + */ + public Pair( T1 left, T2 right ) { + this.left = left; + this.right = right; + } + + @Override + public int compareTo( @NotNull Pair that ) { + //noinspection unchecked + int c = compare( (Comparable) this.left, (Comparable) that.left ); + if ( c == 0 ) { + //noinspection unchecked + c = compare( (Comparable) this.right, (Comparable) that.right ); + } + return c; + } + + + @Override + public T1 getKey() { + return left; + } + + + @Override + public T2 getValue() { + return right; + } + + + @Override + public T2 setValue( T2 value ) { + throw new UnsupportedOperationException(); + } + + public boolean equals( Object obj ) { + return this == obj + || (obj instanceof Pair) + && Objects.equals( this.left, ((Pair) obj).left ) + && Objects.equals( this.right, ((Pair) obj).right ); + } + + /** + * Compares a pair of comparable values of the same type. Null collates less than everything else, but equal to itself. + * + * @param c1 First value + * @param c2 Second value + * @return a negative integer, zero, or a positive integer if c1 is less than, equal to, or greater than c2. + */ + private static > int compare( C c1, C c2 ) { + if ( c1 == null ) { + if ( c2 == null ) { + return 0; + } else { + return -1; + } + } else if ( c2 == null ) { + return 1; + } else { + return c1.compareTo( c2 ); + } + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/ChangePasswordOfRandomUser.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/ChangePasswordOfRandomUser.java new file mode 100644 index 00000000..882bf2ab --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/ChangePasswordOfRandomUser.java @@ -0,0 +1,124 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import com.devskiller.jfairy.Fairy; +import com.devskiller.jfairy.producer.person.Person; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class ChangePasswordOfRandomUser extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + + private final int numberOfUsers; + + + public ChangePasswordOfRandomUser( int numberOfUsers ) { + this.numberOfUsers = numberOfUsers; + } + + + @Override + public Query getNewQuery() { + Fairy fairy = Fairy.create(); + Person person = fairy.person(); + return new ChangePasswordOfRandomUserQuery( + ThreadLocalRandom.current().nextInt( 1, numberOfUsers + 1 ), + person.getPassword() + ); + } + + + private static class ChangePasswordOfRandomUserQuery extends Query { + + private final int userId; + private final String password; + + + private ChangePasswordOfRandomUserQuery( int userId, String password ) { + super( EXPECT_RESULT ); + this.userId = userId; + this.password = password; + } + + + @Override + public String getSql() { + return "UPDATE \"user\" SET \"password\" =" + + "'" + password + "' " + + "WHERE \"id\" = " + + userId; + } + + + @Override + public String getParameterizedSqlQuery() { + return "UPDATE \"user\" SET \"password\" = ? WHERE \"id\" = ?"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.VARCHAR, password ) ); + map.put( 2, new ImmutablePair<>( DataTypes.INTEGER, userId ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + JsonObject set = new JsonObject(); + set.add( "public.user.password", new JsonPrimitive( password ) ); + + Map where = new LinkedHashMap<>(); + where.put( "public.user.id", "=" + userId ); + + return buildRestUpdate( "public.user", set, where ); + } + + + @Override + public String getMongoQl() { + // document model on non-document stores is not yet supported + //return "db.user.update({\"id\":" + userId + "},{\"$set\":{\"password\":" + maybeQuote( password ) + "}})"; + return "db.\"user\".count({\"id\":" + userId + "})"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/ChangeRandomAuction.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/ChangeRandomAuction.java new file mode 100644 index 00000000..c68a1009 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/ChangeRandomAuction.java @@ -0,0 +1,140 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import com.devskiller.jfairy.Fairy; +import com.devskiller.jfairy.producer.text.TextProducer; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; +import org.polypheny.simpleclient.scenario.gavelNG.GavelNGConfig; + + +public class ChangeRandomAuction extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + + private final int numberOfAuctions; + private final int auctionTitleMinLength; + private final int auctionTitleMaxLength; + private final int auctionDescriptionMinLength; + private final int auctionDescriptionMaxLength; + + private final TextProducer text; + + + public ChangeRandomAuction( int numberOfAuctions, GavelNGConfig config ) { + this.numberOfAuctions = numberOfAuctions; + this.auctionTitleMinLength = config.auctionTitleMinLength; + this.auctionTitleMaxLength = config.auctionTitleMaxLength; + this.auctionDescriptionMinLength = config.auctionDescriptionMinLength; + this.auctionDescriptionMaxLength = config.auctionDescriptionMaxLength; + text = Fairy.create().textProducer(); + } + + + @Override + public Query getNewQuery() { + return new ChangeRandomAuctionQuery( + ThreadLocalRandom.current().nextInt( 1, numberOfAuctions + 1 ), + text.latinWord( ThreadLocalRandom.current().nextInt( auctionTitleMinLength, auctionTitleMaxLength + 1 ) ), + text.paragraph( ThreadLocalRandom.current().nextInt( auctionDescriptionMinLength, auctionDescriptionMaxLength + 1 ) ) + ); + } + + + private static class ChangeRandomAuctionQuery extends Query { + + private final int auctionId; + private final String title; + private final String description; + + + public ChangeRandomAuctionQuery( int auctionId, String title, String description ) { + super( EXPECT_RESULT ); + this.auctionId = auctionId; + this.title = title; + this.description = description; + } + + + @Override + public String getSql() { + return "UPDATE auction SET " + + "title = '" + title + "', " + + "description = '" + description + "' " + + "WHERE id = " + + auctionId; + } + + + @Override + public String getParameterizedSqlQuery() { + return "UPDATE auction SET title = ?, description = ? WHERE id = ?"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.VARCHAR, title ) ); + map.put( 2, new ImmutablePair<>( DataTypes.VARCHAR, description ) ); + map.put( 3, new ImmutablePair<>( DataTypes.INTEGER, auctionId ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + JsonObject set = new JsonObject(); + set.add( "public.auction.title", new JsonPrimitive( title ) ); + set.add( "public.auction.description", new JsonPrimitive( description ) ); + + Map where = new LinkedHashMap<>(); + where.put( "public.auction.id", "=" + auctionId ); + + return buildRestUpdate( "public.auction", set, where ); + } + + + @Override + public String getMongoQl() { + // document model on non-document stores is not yet supported + // return "db.auction.update({\"id\":" + auctionId + "},{\"$set\":{ \"description\":" + maybeQuote( description ) + ", \"title\":" + maybeQuote( title ) + "}})"; + return "db.\"auction\".count({\"id\":" + auctionId + "})"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/CountAuction.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/CountAuction.java new file mode 100644 index 00000000..9ac26228 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/CountAuction.java @@ -0,0 +1,117 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.HashMap; +import java.util.Map; +import kong.unirest.HttpRequest; +import kong.unirest.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class CountAuction extends QueryBuilder { + + private static final boolean EXPECT_RESULT = true; + private final QueryMode queryMode; + + + public CountAuction( QueryMode queryMode ) { + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + return new CountAuctionQuery( queryMode ); + } + + + private static class CountAuctionQuery extends Query { + + private final QueryMode queryMode; + + + public CountAuctionQuery( QueryMode queryMode ) { + super( EXPECT_RESULT ); + this.queryMode = queryMode; + } + + + @Override + public String getSql() { + if ( queryMode.equals( QueryMode.VIEW ) ) { + return "SELECT * FROM countAuction"; + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return "SELECT * FROM countAuction_materialized"; + } else { + return "SELECT count(*) as NUMBER FROM auction"; + } + } + + + @Override + public String getParameterizedSqlQuery() { + return getSql(); + } + + + @Override + public Map> getParameterValues() { + return new HashMap<>(); + } + + + @Override + public HttpRequest getRest() { + if ( queryMode.equals( QueryMode.VIEW ) ) { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public.countAuction" ); + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public.countAuction_materialized" ); + } else { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public.auction" ) + .queryString( "_project", "public.auction.id@num(COUNT)" ); + } + } + + + @Override + public String getMongoQl() { + if ( queryMode.equals( QueryMode.VIEW ) ) { + return "db.\"countAuction\".find({})"; + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return "db.\"countAuction_materialized\".find({})"; + } else { + return "db.\"auction\".count({})"; + } + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/CountBid.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/CountBid.java new file mode 100644 index 00000000..8ac06236 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/CountBid.java @@ -0,0 +1,118 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.HashMap; +import java.util.Map; +import kong.unirest.HttpRequest; +import kong.unirest.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class CountBid extends QueryBuilder { + + private static final boolean EXPECT_RESULT = true; + private final QueryMode queryMode; + + + public CountBid( QueryMode queryMode ) { + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + return new CountBidQuery( queryMode ); + } + + + private static class CountBidQuery extends Query { + + private final QueryMode queryMode; + + + public CountBidQuery( QueryMode queryMode ) { + super( EXPECT_RESULT ); + this.queryMode = queryMode; + } + + + @Override + public String getSql() { + if ( queryMode.equals( QueryMode.VIEW ) ) { + return "SELECT * FROM countBid"; + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return "SELECT * FROM countBid_materialized"; + } else { + return "SELECT count(*) as NUMBER FROM bid"; + } + } + + + @Override + public String getParameterizedSqlQuery() { + return getSql(); + } + + + @Override + public Map> getParameterValues() { + return new HashMap<>(); + } + + + @Override + public HttpRequest getRest() { + if ( queryMode.equals( QueryMode.VIEW ) ) { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public.countBid" ); + // .queryString( "public.countBid", "*"); + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public.countBid_materialized" ); + } else { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public.bid" ) + .queryString( "_project", "public.bid.id@num(COUNT)" ); + } + } + + + @Override + public String getMongoQl() { + if ( queryMode.equals( QueryMode.VIEW ) ) { + return "db.\"countBid\".find({})"; + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return "db.\"countBid_materialized\".find({})"; + } else { + return "db.\"bid\".count({})"; + } + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/CountCategory.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/CountCategory.java new file mode 100644 index 00000000..0e6e628a --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/CountCategory.java @@ -0,0 +1,89 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.HashMap; +import java.util.Map; +import kong.unirest.HttpRequest; +import kong.unirest.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class CountCategory extends QueryBuilder { + + private static final boolean EXPECT_RESULT = true; + + + @Override + public Query getNewQuery() { + return new CountCategoryQuery(); + } + + + private static class CountCategoryQuery extends Query { + + public CountCategoryQuery() { + super( EXPECT_RESULT ); + } + + + @Override + public String getSql() { + return "SELECT count(*) as NUMBER FROM category"; + } + + + @Override + public String getParameterizedSqlQuery() { + return getSql(); + } + + + @Override + public Map> getParameterValues() { + return new HashMap<>(); + } + + + @Override + public HttpRequest getRest() { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public.category" ) + .queryString( "_project", "public.category.id@num(COUNT)" ); + } + + + @Override + public String getMongoQl() { + return "db.\"category\".count({})"; + + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/CountUser.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/CountUser.java new file mode 100644 index 00000000..674c72cb --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/CountUser.java @@ -0,0 +1,89 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.HashMap; +import java.util.Map; +import kong.unirest.HttpRequest; +import kong.unirest.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class CountUser extends QueryBuilder { + + private static final boolean EXPECT_RESULT = true; + + + @Override + public Query getNewQuery() { + return new CountUserQuery(); + } + + + private static class CountUserQuery extends Query { + + public CountUserQuery() { + super( EXPECT_RESULT ); + } + + + @Override + public String getSql() { + return "SELECT count(*) as NUMBER FROM \"user\""; + } + + + @Override + public String getParameterizedSqlQuery() { + return getSql(); + } + + + @Override + public Map> getParameterValues() { + return new HashMap<>(); + } + + + @Override + public HttpRequest getRest() { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public.user" ) + .queryString( "_project", "public.user.id@num(COUNT)" ); + } + + + @Override + public String getMongoQl() { + return "db.\"user\".count({})"; + } + + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertAuction.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertAuction.java new file mode 100644 index 00000000..c2a47e60 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertAuction.java @@ -0,0 +1,196 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import com.google.common.collect.ImmutableList; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.Map; +import kong.unirest.HttpRequest; +import lombok.Getter; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.BatchableInsert; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class InsertAuction extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + + private final int userId; + private final int categoryId; + private final int conditionId; + private final LocalDateTime startDate; + private final LocalDateTime endDate; + private final String title; + private final String description; + private final int auctionId; + + + public InsertAuction( int auctionId, int userId, int categoryId, int conditionId, LocalDateTime startDate, LocalDateTime endDate, String title, String description ) { + this.auctionId = auctionId; + this.userId = userId; + this.categoryId = categoryId; + this.conditionId = conditionId; + this.startDate = startDate; + this.endDate = endDate; + this.title = title; + this.description = description; + } + + + @Override + public BatchableInsert getNewQuery() { + return new InsertAuctionQuery( + auctionId, + userId, + categoryId, + conditionId, + startDate, + endDate, + title, + description ); + } + + + @Getter + public static class InsertAuctionQuery extends BatchableInsert { + + private static final String SQL = "INSERT INTO auction(id, title, description, start_date, end_date, category, \"user\", \"condition\") VALUES "; + + private final int auctionId; + private final int userId; + private final int categoryId; + private final int conditionId; + private final LocalDateTime startDate; + private final LocalDateTime endDate; + private final String title; + private final String description; + + + public InsertAuctionQuery( int auctionId, int userId, int categoryId, int conditionId, LocalDateTime startDate, LocalDateTime endDate, String title, String description ) { + super( EXPECT_RESULT ); + this.auctionId = auctionId; + this.userId = userId; + this.categoryId = categoryId; + this.conditionId = conditionId; + this.startDate = startDate; + this.endDate = endDate; + this.title = title; + this.description = description; + } + + + @Override + public String getSql() { + return SQL + getSqlRowExpression(); + } + + + @Override + public String getSqlRowExpression() { + return "(" + + auctionId + "," + + "'" + title + "'," + + "'" + description + "'," + + "timestamp '" + startDate.format( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" ) ) + "'," + + "timestamp '" + endDate.format( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" ) ) + "'," + + categoryId + "," + + userId + "," + + conditionId + + ")"; + } + + + @Override + public String getParameterizedSqlQuery() { + return SQL + "(?, ?, ?, ?, ?, ?, ?, ?)"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.INTEGER, auctionId ) ); + map.put( 2, new ImmutablePair<>( DataTypes.VARCHAR, title ) ); + map.put( 3, new ImmutablePair<>( DataTypes.VARCHAR, description ) ); + map.put( 4, new ImmutablePair<>( DataTypes.TIMESTAMP, Timestamp.valueOf( startDate ) ) ); + map.put( 5, new ImmutablePair<>( DataTypes.TIMESTAMP, Timestamp.valueOf( endDate ) ) ); + map.put( 6, new ImmutablePair<>( DataTypes.INTEGER, categoryId ) ); + map.put( 7, new ImmutablePair<>( DataTypes.INTEGER, userId ) ); + map.put( 8, new ImmutablePair<>( DataTypes.INTEGER, conditionId ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + return buildRestInsert( "public.auction", ImmutableList.of( getRestRowExpression() ) ); + } + + + @Override + public String getMongoQl() { + return "db.auction.insert({\"id\":" + maybeQuote( auctionId ) + + ",\"title\":" + maybeQuote( title ) + + ",\"description\":" + maybeQuote( description ) + + ",\"start_date\":" + startDate.toLocalDate().toEpochDay() + + ",\"end_date\":" + endDate.toLocalDate().toEpochDay() + + ",\"category\":" + maybeQuote( categoryId ) + + ",\"user\":" + maybeQuote( userId ) + + ",\"condition\":" + maybeQuote( conditionId ) + "})"; + } + + + @Override + public JsonObject getRestRowExpression() { + JsonObject row = new JsonObject(); + row.add( "public.auction.id", new JsonPrimitive( auctionId ) ); + row.add( "public.auction.title", new JsonPrimitive( title ) ); + row.add( "public.auction.description", new JsonPrimitive( description ) ); + row.add( "public.auction.start_date", new JsonPrimitive( startDate.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME ) ) ); + row.add( "public.auction.end_date", new JsonPrimitive( endDate.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME ) ) ); + row.add( "public.auction.category", new JsonPrimitive( categoryId ) ); + row.add( "public.auction.user", new JsonPrimitive( userId ) ); + row.add( "public.auction.condition", new JsonPrimitive( conditionId ) ); + return row; + } + + + @Override + public String getEntity() { + return "public.auction"; + } + + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertBid.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertBid.java new file mode 100644 index 00000000..6584a1ce --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertBid.java @@ -0,0 +1,166 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import com.google.common.collect.ImmutableList; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.BatchableInsert; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class InsertBid extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + + private final int auctionId; + private final int userId; + private final int amount; + private final LocalDateTime date; + private static final AtomicInteger nextBidId = new AtomicInteger( 1 ); + + + public InsertBid( int auctionId, int userId, int amount, LocalDateTime date ) { + this.auctionId = auctionId; + this.userId = userId; + this.amount = amount; + this.date = date; + } + + + @Override + public BatchableInsert getNewQuery() { + return new InsertBidQuery( + nextBidId.getAndIncrement(), + auctionId, + userId, + amount, + date ); + } + + + static class InsertBidQuery extends BatchableInsert { + + private static final String SQL = "INSERT INTO bid(id, amount, \"timestamp\", \"user\", auction) VALUES "; + + private final int bidId; + private final int auctionId; + private final int userId; + private final int amount; + private final LocalDateTime date; + + + public InsertBidQuery( int bidId, int auctionId, int userId, int amount, LocalDateTime date ) { + super( EXPECT_RESULT ); + this.bidId = bidId; + this.auctionId = auctionId; + this.userId = userId; + this.amount = amount; + this.date = date; + } + + + @Override + public String getSql() { + return SQL + getSqlRowExpression(); + } + + + @Override + public String getSqlRowExpression() { + return "(" + + bidId + "," + + amount + "," + + "timestamp '" + date.format( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" ) ) + "'," + + userId + "," + + auctionId // This could gets a bug if e.g. parallelized + + ")"; + } + + + @Override + public String getParameterizedSqlQuery() { + return SQL + "(?, ?, ?, ?, ?)"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.INTEGER, bidId ) ); + map.put( 2, new ImmutablePair<>( DataTypes.INTEGER, amount ) ); + map.put( 3, new ImmutablePair<>( DataTypes.TIMESTAMP, Timestamp.valueOf( date ) ) ); + map.put( 4, new ImmutablePair<>( DataTypes.INTEGER, userId ) ); + map.put( 5, new ImmutablePair<>( DataTypes.INTEGER, auctionId ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + return buildRestInsert( "public.bid", ImmutableList.of( getRestRowExpression() ) ); + } + + + @Override + public String getMongoQl() { + return "db.bid.insert({\"id\":" + maybeQuote( bidId ) + + ",\"amount\":" + maybeQuote( amount ) + + ",\"timestamp\":" + date.toLocalDate().toEpochDay() + + ",\"user\":" + maybeQuote( userId ) + + ",\"auction\":" + maybeQuote( auctionId ) + "})"; + } + + + @Override + public JsonObject getRestRowExpression() { + JsonObject row = new JsonObject(); + row.add( "public.bid.id", new JsonPrimitive( bidId ) ); + row.add( "public.bid.amount", new JsonPrimitive( amount ) ); + row.add( "public.bid.timestamp", new JsonPrimitive( date.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME ) ) ); + row.add( "public.bid.user", new JsonPrimitive( userId ) ); + row.add( "public.bid.auction", new JsonPrimitive( auctionId ) ); + return row; + } + + + @Override + public String getEntity() { + return "public.bid"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertCategory.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertCategory.java new file mode 100644 index 00000000..e88221e6 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertCategory.java @@ -0,0 +1,158 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import com.google.common.collect.ImmutableList; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Stream; +import kong.unirest.HttpRequest; +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.BatchableInsert; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class InsertCategory extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + + private final ArrayList categories; + private static final AtomicInteger nextCategoryId = new AtomicInteger( 1 ); + + + public InsertCategory() { + categories = new ArrayList<>(); + try ( InputStream is = ClassLoader.getSystemResourceAsStream( "org/polypheny/simpleclient/scenario/gavel/categories.txt" ) ) { + if ( is == null ) { + throw new RuntimeException( "Categories list file not found!" ); + } + try ( InputStreamReader in = new InputStreamReader( is ) ) { + try ( Stream stream = new BufferedReader( in ).lines() ) { + stream.forEach( categories::add ); + } + } + } catch ( IOException e ) { + throw new RuntimeException( e ); + } + } + + + @Override + public BatchableInsert getNewQuery() { + if ( categories.size() == 0 ) { + throw new RuntimeException( "List of categories is empty" ); + } + return new InsertCategoryQuery( + nextCategoryId.getAndIncrement(), + categories.remove( 0 ) + ); + } + + + private static class InsertCategoryQuery extends BatchableInsert { + + private static final String SQL = "INSERT INTO category(id, name) VALUES "; + + private final int categoryId; + private final String category; + + + public InsertCategoryQuery( int categoryId, String category ) { + super( EXPECT_RESULT ); + this.categoryId = categoryId; + this.category = category; + } + + + @Override + public String getSql() { + return SQL + getSqlRowExpression(); + } + + + @Override + public String getSqlRowExpression() { + return "(" + + categoryId + "," + + "'" + StringEscapeUtils.escapeSql( category ) + "'" + + ")"; + } + + + @Override + public String getParameterizedSqlQuery() { + return SQL + "(?, ?)"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.INTEGER, categoryId ) ); + map.put( 2, new ImmutablePair<>( DataTypes.VARCHAR, category ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + return buildRestInsert( "public.category", ImmutableList.of( getRestRowExpression() ) ); + } + + + @Override + public String getMongoQl() { + return buildMongoQlInsert( "category", ImmutableList.of( "id", "name" ), ImmutableList.of( categoryId, category ) ); + } + + + @Override + public JsonObject getRestRowExpression() { + JsonObject row = new JsonObject(); + row.add( "public.category.id", new JsonPrimitive( categoryId ) ); + row.add( "public.category.name", new JsonPrimitive( category ) ); + return row; + } + + + @Override + public String getEntity() { + return "public.category"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertCondition.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertCondition.java new file mode 100644 index 00000000..4b195118 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertCondition.java @@ -0,0 +1,159 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + +import com.google.common.collect.ImmutableList; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Stream; +import kong.unirest.HttpRequest; +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.BatchableInsert; +import org.polypheny.simpleclient.query.QueryBuilder; + +public class InsertCondition extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + + private static final AtomicInteger nextCategoryId = new AtomicInteger( 1 ); + private final ArrayList conditions; + + + public InsertCondition() { + this.conditions = new ArrayList<>(); + + try ( InputStream is = ClassLoader.getSystemResourceAsStream( "org/polypheny/simpleclient/scenario/gavelNG/conditions.txt" ) ) { + if ( is == null ) { + throw new RuntimeException( "Conditions list file not found!" ); + } + try ( InputStreamReader in = new InputStreamReader( is ) ) { + try ( Stream stream = new BufferedReader( in ).lines() ) { + stream.forEach( conditions::add ); + } + } + } catch ( IOException e ) { + throw new RuntimeException( e ); + } + + + } + + + @Override + public BatchableInsert getNewQuery() { + if ( conditions.size() == 0 ) { + throw new RuntimeException( "List of conditions is empty" ); + } + return new InsertConditionQuery( + nextCategoryId.getAndIncrement(), + conditions.remove( 0 ) + ); + } + + + private static class InsertConditionQuery extends BatchableInsert { + + private static final String SQL = "INSERT INTO \"condition\" (id, \"condition\") VALUES "; + + private final int categoryId; + private final String condition; + + + public InsertConditionQuery( int categoryId, String condition ) { + super( EXPECT_RESULT ); + this.categoryId = categoryId; + this.condition = condition; + } + + + @Override + public String getSql() { + return SQL + getSqlRowExpression(); + } + + + @Override + public String getSqlRowExpression() { + return "(" + + categoryId + "," + + "'" + StringEscapeUtils.escapeSql( condition ) + "'," + + ")"; + } + + + @Override + public String getParameterizedSqlQuery() { + return SQL + "(?, ?)"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.INTEGER, categoryId ) ); + map.put( 2, new ImmutablePair<>( DataTypes.VARCHAR, condition ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + return buildRestInsert( "public.condition", ImmutableList.of( getRestRowExpression() ) ); + } + + + @Override + public String getMongoQl() { + return buildMongoQlInsert( "\"condition\"", ImmutableList.of( "id", "\"condition\"" ), ImmutableList.of( categoryId, condition ) ); + } + + + @Override + public JsonObject getRestRowExpression() { + JsonObject row = new JsonObject(); + row.add( "public.condition.id", new JsonPrimitive( categoryId ) ); + row.add( "public.condition.condition", new JsonPrimitive( condition ) ); + return row; + } + + + @Override + public String getEntity() { + return "public.condition"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertPicture.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertPicture.java new file mode 100644 index 00000000..015e8ee2 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertPicture.java @@ -0,0 +1,152 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import com.google.common.collect.ImmutableList; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.BatchableInsert; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class InsertPicture extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + private final static String[] IMAGE_TYPES = { ".tif", ".tiff", ".gif", ".jpeg", ".jpg", ".jif", ".jfif", ".jp2", ".jpx", ".j2k", ".j2c", ".png", ".bmp" }; + + private final int auctionId; + + + public InsertPicture( int auctionId ) { + this.auctionId = auctionId; + } + + + @Override + public BatchableInsert getNewQuery() { + return new InsertPictureQuery( + auctionId, + UUID.randomUUID().toString(), + ThreadLocalRandom.current().nextInt( 100, 2048 ), + IMAGE_TYPES[ThreadLocalRandom.current().nextInt( 0, IMAGE_TYPES.length )] + ); + } + + + private static class InsertPictureQuery extends BatchableInsert { + + private static final String SQL = "INSERT INTO picture(filename, type, size, auction) VALUES "; + + private final int auctionId; + private final String fileName; + private final int size; + private final String fileType; + + + public InsertPictureQuery( int auctionId, String fileName, int size, String fileType ) { + super( EXPECT_RESULT ); + this.auctionId = auctionId; + this.fileName = fileName; + this.size = size; + this.fileType = fileType; + } + + + @Override + public String getSql() { + return SQL + getSqlRowExpression(); + } + + + @Override + public String getSqlRowExpression() { + return "(" + + "'" + fileName + "'," + + "'" + fileType + "'," + + size + "," + + auctionId + + ")"; + } + + + @Override + public String getParameterizedSqlQuery() { + return SQL + "(?, ?, ?, ?)"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.VARCHAR, fileName ) ); + map.put( 2, new ImmutablePair<>( DataTypes.VARCHAR, fileType ) ); + map.put( 3, new ImmutablePair<>( DataTypes.INTEGER, size ) ); + map.put( 4, new ImmutablePair<>( DataTypes.INTEGER, auctionId ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + return buildRestInsert( "public.picture", ImmutableList.of( getRestRowExpression() ) ); + } + + + @Override + public String getMongoQl() { + return "db.picture.insert({\"filename\":" + fileName + + ",\"type\":" + fileType + + ",\"size\":" + size + + ",\"auction\":" + auctionId + "})"; + } + + + @Override + public JsonObject getRestRowExpression() { + JsonObject row = new JsonObject(); + row.add( "public.picture.filename", new JsonPrimitive( fileName ) ); + row.add( "public.picture.type", new JsonPrimitive( fileType ) ); + row.add( "public.picture.size", new JsonPrimitive( size ) ); + row.add( "public.picture.auction", new JsonPrimitive( auctionId ) ); + return row; + } + + + @Override + public String getEntity() { + return "public.picture"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertRandomAuction.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertRandomAuction.java new file mode 100644 index 00000000..beed5543 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertRandomAuction.java @@ -0,0 +1,111 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import com.devskiller.jfairy.Fairy; +import com.devskiller.jfairy.producer.DateProducer; +import com.devskiller.jfairy.producer.text.TextProducer; +import java.time.LocalDateTime; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicInteger; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; +import org.polypheny.simpleclient.scenario.gavelNG.GavelNGConfig; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.InsertAuction.InsertAuctionQuery; + + +public class InsertRandomAuction extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + + private final int numberOfUsers; + private final int numberOfCategories; + private final int numberOfConditions; + private final int auctionTitleMinLength; + private final int auctionTitleMaxLength; + private final int auctionDescriptionMinLength; + private final int auctionDescriptionMaxLength; + private final int auctionDateMaxYearsInPast; + private final int auctionNumberOfDays; + + private final TextProducer text; + private final DateProducer dateProducer; + + private static final AtomicInteger nextAuctionId = new AtomicInteger( 1 ); + + + public InsertRandomAuction( int numberOfUsers, int numberOfCategories, int numberOfConditions, GavelNGConfig config ) { + this.numberOfUsers = numberOfUsers; + this.numberOfCategories = numberOfCategories; + this.numberOfConditions = numberOfConditions; + this.auctionTitleMinLength = config.auctionTitleMinLength; + this.auctionTitleMaxLength = config.auctionTitleMaxLength; + this.auctionDescriptionMinLength = config.auctionDescriptionMinLength; + this.auctionDescriptionMaxLength = config.auctionDescriptionMaxLength; + this.auctionDateMaxYearsInPast = config.auctionDateMaxYearsInPast; + this.auctionNumberOfDays = config.auctionNumberOfDays; + + text = Fairy.create().textProducer(); + dateProducer = Fairy.create().dateProducer(); + } + + + public static void setNextId( int nextId ) { + InsertRandomAuction.nextAuctionId.set( nextId ); + } + + + @Override + public Query getNewQuery() { + String title = text.latinWord( ThreadLocalRandom.current().nextInt( auctionTitleMinLength, auctionTitleMaxLength + 1 ) ); + String description = text.paragraph( ThreadLocalRandom.current().nextInt( auctionDescriptionMinLength, auctionDescriptionMaxLength + 1 ) ); + LocalDateTime startDate = dateProducer.randomDateInThePast( auctionDateMaxYearsInPast ); + LocalDateTime endDate = startDate.plusDays( auctionNumberOfDays ); + + return new InsertRandomAuctionQuery( + nextAuctionId.getAndIncrement(), + title, + description, + startDate, + endDate, + ThreadLocalRandom.current().nextInt( 1, numberOfUsers + 1 ), + ThreadLocalRandom.current().nextInt( 1, numberOfCategories + 1 ), + ThreadLocalRandom.current().nextInt( 1, numberOfConditions + 1 ) + ); + } + + + private static class InsertRandomAuctionQuery extends InsertAuctionQuery { + + + public InsertRandomAuctionQuery( int auctionId, String title, String description, LocalDateTime startDate, LocalDateTime endDate, int userId, int categoryId, int conditionsId ) { + super( auctionId, userId, categoryId, conditionsId, startDate, endDate, title, description ); + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertRandomBid.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertRandomBid.java new file mode 100644 index 00000000..b9344645 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertRandomBid.java @@ -0,0 +1,81 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import com.devskiller.jfairy.Fairy; +import com.devskiller.jfairy.producer.DateProducer; +import java.time.LocalDateTime; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicInteger; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; +import org.polypheny.simpleclient.scenario.gavelNG.queryBuilder.InsertBid.InsertBidQuery; + + +public class InsertRandomBid extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + + private final int numberOfAuctions; + private final int numberOfUsers; + + private static final AtomicInteger nextBidId = new AtomicInteger( 1 ); + + + public InsertRandomBid( int numberOfAuctions, int numberOfUsers ) { + this.numberOfAuctions = numberOfAuctions; + this.numberOfUsers = numberOfUsers; + } + + + public static void setNextId( int nextId ) { + InsertRandomBid.nextBidId.set( nextId ); + } + + + @Override + public Query getNewQuery() { + DateProducer dateProducer = Fairy.create().dateProducer(); + return new InsertRandomBidQuery( + nextBidId.getAndIncrement(), + ThreadLocalRandom.current().nextInt( 1, 1000 ), + dateProducer.randomDateInThePast( 5 ), + ThreadLocalRandom.current().nextInt( 1, numberOfUsers + 1 ), + ThreadLocalRandom.current().nextInt( 1, numberOfAuctions + 1 ) + ); + } + + + private static class InsertRandomBidQuery extends InsertBidQuery { + + public InsertRandomBidQuery( int bidId, int amount, LocalDateTime timestamp, int userId, int auctionId ) { + super( bidId, auctionId, userId, amount, timestamp ); + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertUser.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertUser.java new file mode 100644 index 00000000..a377d273 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/InsertUser.java @@ -0,0 +1,236 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import com.devskiller.jfairy.Fairy; +import com.devskiller.jfairy.producer.person.Person; +import com.google.common.collect.ImmutableList; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CodingErrorAction; +import java.nio.charset.StandardCharsets; +import java.sql.Date; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.atomic.AtomicInteger; +import kong.unirest.HttpRequest; +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.BatchableInsert; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class InsertUser extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + + private static final AtomicInteger nextUserId = new AtomicInteger( 1 ); + + private static final Random RANDOM = new Random(); + private static final CharsetDecoder DECODER = StandardCharsets.ISO_8859_1.newDecoder(); + private static final CharsetEncoder ENCODER = StandardCharsets.ISO_8859_1.newEncoder(); + + private static final Locale[] locales = { + new Locale( "de" ), + new Locale( "en" ), + new Locale( "es" ), + new Locale( "fr" ), + new Locale( "it" ), + //new Locale( "ka" ), + //new Locale( "pl" ), + //new Locale( "sv" ), + //new Locale( "zh" ), + }; + + + static { + ENCODER.onUnmappableCharacter( CodingErrorAction.IGNORE ); + DECODER.onUnmappableCharacter( CodingErrorAction.IGNORE ); + } + + + @Override + public BatchableInsert getNewQuery() { + Fairy fairy = Fairy.create( locales[RANDOM.nextInt( locales.length )] ); + Person person = fairy.person(); + return new InsertUserQuery( + nextUserId.getAndIncrement(), + person.getEmail(), + person.getPassword(), + person.getLastName(), + person.getFirstName(), + person.getSex().name().substring( 0, 1 ).toLowerCase(), + person.getDateOfBirth(), + person.getAddress().getCity(), + person.getAddress().getPostalCode(), + person.getNationality().name() + ); + } + + + private static class InsertUserQuery extends BatchableInsert { + + private static final String SQL = "INSERT INTO \"user\"(id, email, password, last_name, first_name, gender, birthday, city, zip_code, country) VALUES "; + + private final int userId; + private final String email; + private final String password; + private final String lastName; + private final String firstName; + private final String gender; + private final LocalDate birthday; + private final String city; + private final String zipCode; + private final String country; + + + public InsertUserQuery( int userId, String email, String password, String lastName, String firstName, String gender, LocalDate birthday, String city, String zipCode, String country ) { + super( EXPECT_RESULT ); + this.userId = userId; + this.email = email; + this.password = password; + this.lastName = lastName; + this.firstName = firstName; + this.gender = gender; + this.birthday = birthday; + this.city = city; + this.zipCode = zipCode; + this.country = country; + } + + + @Override + public String getSql() { + return SQL + getSqlRowExpression(); + } + + + @Override + public String getSqlRowExpression() { + return "(" + + userId + "," + + "'" + escapeAndConvert( email ) + "'," + + "'" + escapeAndConvert( password ) + "'," + + "'" + escapeAndConvert( lastName ) + "'," + + "'" + escapeAndConvert( firstName ) + "'," + + "'" + gender + "'," + + "date '" + birthday.format( DateTimeFormatter.ofPattern( "yyyy-MM-dd" ) ) + "'," + + "'" + escapeAndConvert( city ) + "'," + + "'" + zipCode + "'," + + "'" + country + "'" + + ")"; + } + + + @Override + public String getParameterizedSqlQuery() { + return SQL + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.INTEGER, userId ) ); + map.put( 2, new ImmutablePair<>( DataTypes.VARCHAR, email ) ); + map.put( 3, new ImmutablePair<>( DataTypes.VARCHAR, password ) ); + map.put( 4, new ImmutablePair<>( DataTypes.VARCHAR, lastName ) ); + map.put( 5, new ImmutablePair<>( DataTypes.VARCHAR, firstName ) ); + map.put( 6, new ImmutablePair<>( DataTypes.VARCHAR, gender ) ); + map.put( 7, new ImmutablePair<>( DataTypes.DATE, Date.valueOf( birthday ) ) ); + map.put( 8, new ImmutablePair<>( DataTypes.VARCHAR, city ) ); + map.put( 9, new ImmutablePair<>( DataTypes.VARCHAR, zipCode ) ); + map.put( 10, new ImmutablePair<>( DataTypes.VARCHAR, country ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + return buildRestInsert( "public.user", ImmutableList.of( getRestRowExpression() ) ); + } + + + @Override + public String getMongoQl() { + return "db.\"user\".insert({\"id\":" + maybeQuote( userId ) + + ",\"email\":" + maybeQuote( email ) + + ",\"password\":" + maybeQuote( password ) + + ",\"last_name\":" + maybeQuote( lastName ) + + ",\"first_name\":" + maybeQuote( firstName ) + + ",\"gender\":" + maybeQuote( gender ) + + ",\"birthday\":" + birthday.toEpochDay() + + ",\"city\":" + maybeQuote( city ) + + ",\"zip_code\":" + maybeQuote( zipCode ) + + ",\"country\":" + maybeQuote( country ) + "})"; + } + + + @Override + public JsonObject getRestRowExpression() { + JsonObject row = new JsonObject(); + row.add( "public.user.id", new JsonPrimitive( userId ) ); + row.add( "public.user.email", new JsonPrimitive( escapeAndConvert( email ) ) ); + row.add( "public.user.password", new JsonPrimitive( escapeAndConvert( password ) ) ); + row.add( "public.user.last_name", new JsonPrimitive( escapeAndConvert( lastName ) ) ); + row.add( "public.user.first_name", new JsonPrimitive( escapeAndConvert( firstName ) ) ); + row.add( "public.user.gender", new JsonPrimitive( gender ) ); + row.add( "public.user.birthday", new JsonPrimitive( birthday.format( DateTimeFormatter.ISO_LOCAL_DATE ) ) ); + row.add( "public.user.city", new JsonPrimitive( escapeAndConvert( city ) ) ); + row.add( "public.user.zip_code", new JsonPrimitive( zipCode ) ); + row.add( "public.user.country", new JsonPrimitive( country ) ); + return row; + } + + + @Override + public String getEntity() { + return "public.user"; + } + + + private String escapeAndConvert( String s ) { + try { + synchronized ( DECODER ) { + return DECODER.decode( ENCODER.encode( CharBuffer.wrap( StringEscapeUtils.escapeSql( s ) ) ) ).toString(); + } + } catch ( CharacterCodingException e ) { + throw new RuntimeException( e ); + } + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SearchAuction.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SearchAuction.java new file mode 100644 index 00000000..19370ddd --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SearchAuction.java @@ -0,0 +1,127 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import com.devskiller.jfairy.Fairy; +import com.devskiller.jfairy.producer.text.TextProducer; +import java.util.HashMap; +import java.util.Map; +import kong.unirest.HttpRequest; +import kong.unirest.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class SearchAuction extends QueryBuilder { + + private static final boolean EXPECT_RESULT = true; + + private final TextProducer text; + private final QueryMode queryMode; + + + public SearchAuction( QueryMode queryMode ) { + text = Fairy.create().textProducer(); + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + return new SearchAuctionQuery( text.latinWord( 2 ), queryMode ); + } + + + private static class SearchAuctionQuery extends Query { + + private final String searchString; + private final String tableName; + + + public SearchAuctionQuery( String searchString, QueryMode queryMode ) { + super( EXPECT_RESULT ); + this.searchString = searchString; + + if ( queryMode.equals( QueryMode.VIEW ) ) { + tableName = "auction_view"; + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + tableName = "auction_materialized"; + } else { + tableName = "auction"; + } + } + + + @Override + public String getSql() { + return "SELECT a.title, a.start_date, a.end_date FROM " + tableName + " a " + + "WHERE a.title LIKE '%" + searchString + "%' " + + "ORDER BY end_date desc " + + "LIMIT 100"; + } + + + @Override + public String getParameterizedSqlQuery() { + return "SELECT a.title, a.start_date, a.end_date FROM " + tableName + " a " + + "WHERE a.title LIKE ? " + + "ORDER BY end_date desc " + + "LIMIT 100"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.VARCHAR, "%" + searchString + "%" ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public.auction" ) + .queryString( "_project", "public." + tableName + ".title,public." + tableName + ".start_date,public." + tableName + ".end_date" ) + .queryString( "public." + tableName + ".title", "%%" + searchString + "%" ) + .queryString( "_sort", "public." + tableName + ".end_date@DESC" ) + .queryString( "_limit", 100 ); + } + + + @Override + public String getMongoQl() { + return "db." + tableName + ".aggregate([" + + "{\"$match\":{\"title\":{\"$regex\": \"/$" + searchString + "$/\"}}}," + + "{\"$sort\":{\"end_data\": -1}}," + + "{\"$limit\": 100}])"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectAllActiveAuctions.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectAllActiveAuctions.java new file mode 100644 index 00000000..2d53fe1e --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectAllActiveAuctions.java @@ -0,0 +1,108 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.HashMap; +import java.util.Map; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class SelectAllActiveAuctions extends QueryBuilder { + + + private static final boolean EXPECT_RESULT = true; + private final QueryMode queryMode; + + + public SelectAllActiveAuctions( QueryMode queryMode ) { + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + return new SelectAllActiveAuctionsQuery( queryMode ); + } + + + private static class SelectAllActiveAuctionsQuery extends Query { + + private final QueryMode queryMode; + + + public SelectAllActiveAuctionsQuery( QueryMode queryMode ) { + super( EXPECT_RESULT ); + this.queryMode = queryMode; + } + + + @Override + public String getSql() { + if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return "SELECT * FROM allActiveAuctions_materialized LIMIT 100"; + } else if ( queryMode.equals( QueryMode.VIEW ) ) { + return "SELECT * FROM allActiveAuctions_view LIMIT 100"; + } else { + + return "SELECT \"public\".\"auction\".\"title\", \"public\".\"auction\".\"end_date\" " + + "FROM \"public\".\"auction\" " + + "WHERE \"public\".\"auction\".\"end_date\" > '2020-11-25 12:43:21' "; + } + } + + + @Override + public String getParameterizedSqlQuery() { + return getSql(); + } + + + @Override + public Map> getParameterValues() { + return new HashMap<>(); + } + + + @Override + public HttpRequest getRest() { + return null; + } + + + @Override + public String getMongoQl() { + // $lookup not yet supported + return null; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectAllBidsOnRandomAuction.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectAllBidsOnRandomAuction.java new file mode 100644 index 00000000..76e39ed4 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectAllBidsOnRandomAuction.java @@ -0,0 +1,115 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; +import kong.unirest.HttpRequest; +import kong.unirest.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class SelectAllBidsOnRandomAuction extends QueryBuilder { + + private static final boolean EXPECT_RESULT = true; + + private final int numberOfAuctions; + private final QueryMode queryMode; + + + public SelectAllBidsOnRandomAuction( int numberOfAuctions, QueryMode queryMode ) { + this.numberOfAuctions = numberOfAuctions; + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + int auctionId = ThreadLocalRandom.current().nextInt( 1, numberOfAuctions + 1 ); + return new SelectAllBidsOnRandomAuctionQuery( auctionId, queryMode ); + } + + + private static class SelectAllBidsOnRandomAuctionQuery extends Query { + + private final int auctionId; + private final String tableName; + + + public SelectAllBidsOnRandomAuctionQuery( int auctionId, QueryMode queryMode ) { + super( EXPECT_RESULT ); + this.auctionId = auctionId; + + if ( queryMode.equals( QueryMode.VIEW ) ) { + tableName = "bid_view"; + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + tableName = "bid_materialized"; + } else { + tableName = "bid"; + } + } + + + @Override + public String getSql() { + return "SELECT * FROM " + tableName + " b WHERE b.auction=" + auctionId; + } + + + @Override + public String getParameterizedSqlQuery() { + return "SELECT * FROM " + tableName + " b WHERE b.auction=?"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.INTEGER, auctionId ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public." + tableName ) + .queryString( "public." + tableName + ".auction", "=" + auctionId ); + } + + + @Override + public String getMongoQl() { + return "db." + tableName + ".find({\"auction\":" + auctionId + "})"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectDifferenceBetweenLowestAndHighestBid.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectDifferenceBetweenLowestAndHighestBid.java new file mode 100644 index 00000000..4668c4d2 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectDifferenceBetweenLowestAndHighestBid.java @@ -0,0 +1,118 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.HashMap; +import java.util.Map; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class SelectDifferenceBetweenLowestAndHighestBid extends QueryBuilder { + + + private static final boolean EXPECT_RESULT = true; + private final QueryMode queryMode; + + + public SelectDifferenceBetweenLowestAndHighestBid( QueryMode queryMode ) { + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + return new SelectDifferenceBetweenLowestAndHighestBidQuery( queryMode ); + } + + + private static class SelectDifferenceBetweenLowestAndHighestBidQuery extends Query { + + private final QueryMode queryMode; + + + public SelectDifferenceBetweenLowestAndHighestBidQuery( QueryMode queryMode ) { + super( EXPECT_RESULT ); + this.queryMode = queryMode; + } + + + @Override + public String getSql() { + if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return "SELECT * FROM differenceBetweenLowestAndHighestBid_materialized LIMIT 100"; + } else if ( queryMode.equals( QueryMode.VIEW ) ) { + return "SELECT * FROM differenceBetweenLowestAndHighestBid_view LIMIT 100"; + } else { + return "SELECT difference, title " + + "FROM " + + "(SELECT (a.maxamount - a.minamount) as difference, a.auctionid as auctionid " + + "FROM " + + "(SELECT min(\"public\".\"bid\".\"amount\") as \"minamount\", max(\"public\".\"bid\".\"amount\") as \"maxamount\", \"public\".\"bid\".\"auction\" as \"auctionid\" " + + "FROM \"public\".\"bid\" " + + "WHERE \"public\".\"bid\".\"auction\" in ( SELECT \"public\".\"auction\".\"id\" FROM \"public\".\"auction\" ) " + + "GROUP BY \"public\".\"bid\".\"auction\") as \"a\")as \"b\" " + + "JOIN " + + "(SELECT \"public\".\"auction\".\"title\" as \"title\", \"public\".\"auction\".\"id\" as \"auctionid\" " + + "FROM \"public\".\"auction\") as \"c\" " + + "on b.auctionid = c.auctionid " + + "GROUP BY title, difference " + + "LIMIT 100 "; + } + } + + + @Override + public String getParameterizedSqlQuery() { + return getSql(); + } + + + @Override + public Map> getParameterValues() { + return new HashMap<>(); + } + + + @Override + public HttpRequest getRest() { + return null; + } + + + @Override + public String getMongoQl() { + // $lookup not yet supported + return null; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectHighestBidOnRandomAuction.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectHighestBidOnRandomAuction.java new file mode 100644 index 00000000..e00740b7 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectHighestBidOnRandomAuction.java @@ -0,0 +1,121 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; +import kong.unirest.HttpRequest; +import kong.unirest.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class SelectHighestBidOnRandomAuction extends QueryBuilder { + + private static final boolean EXPECT_RESULT = true; + + private final int numberOfAuctions; + private final QueryMode queryMode; + + + public SelectHighestBidOnRandomAuction( int numberOfAuctions, QueryMode queryMode ) { + this.numberOfAuctions = numberOfAuctions; + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + int auctionId = ThreadLocalRandom.current().nextInt( 1, numberOfAuctions + 1 ); + return new SelectHighestBidOnRandomAuctionQuery( auctionId, queryMode ); + } + + + private static class SelectHighestBidOnRandomAuctionQuery extends Query { + + private final int auctionId; + private final String tableName; + + + public SelectHighestBidOnRandomAuctionQuery( int auctionId, QueryMode queryMode ) { + super( EXPECT_RESULT ); + this.auctionId = auctionId; + + if ( queryMode.equals( QueryMode.VIEW ) ) { + tableName = "bid_view"; + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + tableName = "bid_materialized"; + } else { + tableName = "bid"; + } + } + + + @Override + public String getSql() { + return "SELECT * FROM " + tableName + " b WHERE b.auction=" + auctionId + " ORDER BY b.amount desc LIMIT 1"; + } + + + @Override + public String getParameterizedSqlQuery() { + return "SELECT * FROM " + tableName + " b WHERE b.auction=? ORDER BY b.amount desc LIMIT 1"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.INTEGER, auctionId ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public." + tableName ) + .queryString( "public." + tableName + ".auction", "=" + auctionId ) + .queryString( "_sort", "public." + tableName + ".amount@DESC" ) + .queryString( "_limit", "1" ); + } + + + @Override + public String getMongoQl() { + return "db." + tableName + ".aggregate([" + + "{\"$match\":{ \"auction\":" + auctionId + "}}, " + + "{\"$sort\":{\"amount\": -1}}," + + "{\"$limit\":1}" + + "])"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectHighestOverallBid.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectHighestOverallBid.java new file mode 100644 index 00000000..dae91a2c --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectHighestOverallBid.java @@ -0,0 +1,133 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + +import java.util.HashMap; +import java.util.Map; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class SelectHighestOverallBid extends QueryBuilder { + + private static final boolean EXPECT_RESULT = true; + private final QueryMode queryMode; + + + public SelectHighestOverallBid( QueryMode queryMode ) { + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + return new SelectHighestOverallBidQuery( queryMode ); + } + + + private static class SelectHighestOverallBidQuery extends Query { + + private final QueryMode queryMode; + + + public SelectHighestOverallBidQuery( QueryMode queryMode ) { + super( EXPECT_RESULT ); + this.queryMode = queryMode; + } + + + @Override + public String getSql() { + if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return "SELECT * FROM highestBid_materialized LIMIT 1"; + } else if ( queryMode.equals( QueryMode.VIEW ) ) { + return "SELECT * FROM highestBid_view LIMIT 1"; + } else { + return "SELECT last_name, first_name " + + "FROM \"user\" " + + "WHERE \"user\".id = (SELECT highest.highestUser FROM (SELECT bid.\"user\" as highestUser, MAX( bid.amount) " + + "FROM public.bid " + + "GROUP BY bid.\"user\" " + + "ORDER BY MAX( bid.amount) DESC) as highest Limit 1) LIMIT 1"; + } + } + + + @Override + public String getParameterizedSqlQuery() { + return getSql(); + } + + + @Override + public Map> getParameterValues() { + return new HashMap<>(); + } + + + @Override + public HttpRequest getRest() { + return null; + + /* + if ( queryMode.equals( QueryMode.VIEW ) ) { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public.highestBid_view" ) + .queryString( "_limit", 100 ); + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public.highestBid_materialized" ) + .queryString( "_limit", 100 ); + } else { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public.user" ) + .queryString( "_project", "public.user.last_name,public.user.first_name") + .queryString( "public.bid.user", "=" + "public.user.id" ) + .queryString( "public.bid.auction", "=" + "public.auction.id" ) + .queryString( "public.picture.auction", "=" + "public.auction.id" ) + .queryString( "public.auction.user", "=" + "public.user.id" ) + .queryString( "public.auction.category", "=" + "public.category.id" ) + .queryString( "_limit", 100 ); + } + */ + } + + + @Override + public String getMongoQl() { + // $lookup is not supported // substitute query + + return "db.bid.aggregate([" + + "{\"$group\":{\"_id\": \"user\", \"max_amount\":{\"$max\": \"amount\"}}}," + + "{\"$sort\":{\"max_amount\": -1 }}," + + "{\"$project\":{\"highestUser\": \"$user\", \"max_amount\": 1}}," + + "{\"$limit\": 1}])"; + } + + } + +} + diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectMaxAmountConditionFinishedAuctions.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectMaxAmountConditionFinishedAuctions.java new file mode 100644 index 00000000..d7604e04 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectMaxAmountConditionFinishedAuctions.java @@ -0,0 +1,117 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.HashMap; +import java.util.Map; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class SelectMaxAmountConditionFinishedAuctions extends QueryBuilder { + + + private static final boolean EXPECT_RESULT = true; + private final QueryMode queryMode; + + + public SelectMaxAmountConditionFinishedAuctions( QueryMode queryMode ) { + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + return new SelectMaxAmountConditionFinishedAuctionsQuery( queryMode ); + } + + + private static class SelectMaxAmountConditionFinishedAuctionsQuery extends Query { + + private final QueryMode queryMode; + + + public SelectMaxAmountConditionFinishedAuctionsQuery( QueryMode queryMode ) { + super( EXPECT_RESULT ); + this.queryMode = queryMode; + } + + + @Override + public String getSql() { + if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return "SELECT * FROM maxAmountConditionFinishedAuctions_materialized LIMIT 100"; + } else if ( queryMode.equals( QueryMode.VIEW ) ) { + return "SELECT * FROM maxAmountConditionFinishedAuctions_view LIMIT 100"; + } else { + return "SELECT b.\"maxamount\", \"d\".\"condition\" " + + "FROM " + + "(SELECT a.\"maxamount\", \"c\".\"condition\" " + + "FROM " + + "(SELECT max(\"public\".\"bid\".\"amount\") as \"maxamount\", \"public\".\"bid\".\"auction\" as \"auctionid\" " + + "FROM \"public\".\"bid\" " + + "WHERE \"public\".\"bid\".\"auction\" in " + + "( SELECT \"public\".\"auction\".\"id\" " + + "FROM \"public\".\"auction\" " + + "WHERE \"end_date\" < '2020-11-25 12:43:21') " + + "Group by \"public\".\"bid\".\"auction\") as \"a\" " + + "INNER JOIN \"public\".\"auction\" as \"c\" ON a.auctionid = \"c\".\"id\") as \"b\" " + + "INNER JOIN \"public\".\"condition\" as \"d\" ON \"b\".\"condition\" = d.\"id\""; + } + } + + + @Override + public String getParameterizedSqlQuery() { + return getSql(); + } + + + @Override + public Map> getParameterValues() { + return new HashMap<>(); + } + + + @Override + public HttpRequest getRest() { + return null; + } + + + @Override + public String getMongoQl() { + // $lookup not yet supported + return null; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectOtherInterestingActiveAuctions.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectOtherInterestingActiveAuctions.java new file mode 100644 index 00000000..1a4514a9 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectOtherInterestingActiveAuctions.java @@ -0,0 +1,113 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.HashMap; +import java.util.Map; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class SelectOtherInterestingActiveAuctions extends QueryBuilder { + + + private static final boolean EXPECT_RESULT = true; + private final QueryMode queryMode; + + + public SelectOtherInterestingActiveAuctions( QueryMode queryMode ) { + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + return new SelectOtherInterestingActiveAuctionsQuery( queryMode ); + } + + + private static class SelectOtherInterestingActiveAuctionsQuery extends Query { + + private final QueryMode queryMode; + + + public SelectOtherInterestingActiveAuctionsQuery( QueryMode queryMode ) { + super( EXPECT_RESULT ); + this.queryMode = queryMode; + } + + + @Override + public String getSql() { + if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return "SELECT * FROM otherInterestingActiveAuctions_materialized LIMIT 100"; + } else if ( queryMode.equals( QueryMode.VIEW ) ) { + return "SELECT * FROM otherInterestingActiveAuctions_view LIMIT 100"; + } else { + return "SELECT c.last_name,a.title, a.end_date " + + "FROM " + + "(SELECT \"public\".\"user\".\"last_name\" as \"last_name\", \"public\".\"auction\".\"category\" as \"categoryid\", \"public\".\"auction\".\"condition\" as \"conditionid\" " + + "FROM \"public\".\"user\",\"public\".\"auction\" " + + "WHERE \"public\".\"auction\".\"user\" = \"public\".\"user\".\"id\" " + + "AND \"public\".\"auction\".\"end_date\" < '2020-11-25 12:43:21' " + + "Limit 1) as \"c\", \"public\".\"auction\" as \"a\" " + + "WHERE (c.categoryid = a.category OR c.conditionid = a.\"condition\") AND a.end_date > '2020-11-25 12:43:21' " + + "LIMIT 100"; + } + } + + + @Override + public String getParameterizedSqlQuery() { + return getSql(); + } + + + @Override + public Map> getParameterValues() { + return new HashMap<>(); + } + + + @Override + public HttpRequest getRest() { + return null; + } + + + @Override + public String getMongoQl() { + // $lookup not yet supported + return null; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectPriceBetweenAndNotInCategory.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectPriceBetweenAndNotInCategory.java new file mode 100644 index 00000000..db85523f --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectPriceBetweenAndNotInCategory.java @@ -0,0 +1,111 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + +import java.util.HashMap; +import java.util.Map; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class SelectPriceBetweenAndNotInCategory extends QueryBuilder { + + public static final boolean EXPECT_RESULT = true; + private final QueryMode queryMode; + + + public SelectPriceBetweenAndNotInCategory( QueryMode queryMode ) { + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + return new SelectPriceBetweenAndNotInCategoryQuery( queryMode ); + } + + + private static class SelectPriceBetweenAndNotInCategoryQuery extends Query { + + private final QueryMode queryMode; + + + public SelectPriceBetweenAndNotInCategoryQuery( QueryMode queryMode ) { + super( EXPECT_RESULT ); + this.queryMode = queryMode; + } + + + @Override + public String getSql() { + if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return "SELECT * FROM priceBetween_materialized LIMIT 100"; + } else if ( queryMode.equals( QueryMode.VIEW ) ) { + return "SELECT * FROM priceBetween_view LIMIT 100"; + } else { + return "SELECT auction.title, bid.amount " + + "FROM auction, category, bid " + + "WHERE bid.auction = auction.id " + + "AND bid.amount > 1000 AND bid.amount < 1000000 " + + "ORDER BY bid.amount DESC LIMIT 100"; + } + } + + + @Override + public String getParameterizedSqlQuery() { + return getSql(); + } + + + @Override + public Map> getParameterValues() { + return new HashMap<>(); + } + + + @Override + public HttpRequest getRest() { + return null; + } + + + @Override + public String getMongoQl() { + // $lookup is not supported // substitute query + return "db.bid.aggregate([" + + "{\"$match\":{\"$or\":[{\"amount\":{\"$gt\": 1000}}, {\"amount\":{\"$lt\": 1000000}}]}}, " + + "{\"$sort\":{\"amount\": -1 }}, " + + "{\"$limit\":100}" + + "])"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectRandomAuction.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectRandomAuction.java new file mode 100644 index 00000000..0d084182 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectRandomAuction.java @@ -0,0 +1,115 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; +import kong.unirest.HttpRequest; +import kong.unirest.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class SelectRandomAuction extends QueryBuilder { + + private static final boolean EXPECT_RESULT = true; + + private final int numberOfAuctions; + private final QueryMode queryMode; + + + public SelectRandomAuction( int numberOfAuctions, QueryMode queryMode ) { + this.numberOfAuctions = numberOfAuctions; + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + int auctionId = ThreadLocalRandom.current().nextInt( 1, numberOfAuctions + 1 ); + return new SelectRandomAuctionQuery( auctionId, queryMode ); + } + + + private static class SelectRandomAuctionQuery extends Query { + + private final int auctionId; + private final String tableName; + + + public SelectRandomAuctionQuery( int auctionId, QueryMode queryMode ) { + super( EXPECT_RESULT ); + this.auctionId = auctionId; + + if ( queryMode.equals( QueryMode.VIEW ) ) { + tableName = "auction_view"; + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + tableName = "auction_materialized"; + } else { + tableName = "auction"; + } + } + + + @Override + public String getSql() { + return "SELECT * FROM " + tableName + " a WHERE a.id=" + auctionId; + } + + + @Override + public String getParameterizedSqlQuery() { + return "SELECT * FROM " + tableName + " a WHERE a.id=?"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.INTEGER, auctionId ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public." + tableName ) + .queryString( "public." + tableName + ".id", "=" + auctionId ); + } + + + @Override + public String getMongoQl() { + return "db." + tableName + ".find({\"id\":" + auctionId + "})"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectRandomBid.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectRandomBid.java new file mode 100644 index 00000000..3c735f78 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectRandomBid.java @@ -0,0 +1,115 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; +import kong.unirest.HttpRequest; +import kong.unirest.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class SelectRandomBid extends QueryBuilder { + + private static final boolean EXPECT_RESULT = true; + + private final int numberOfBids; + private final QueryMode queryMode; + + + public SelectRandomBid( int numberOfBids, QueryMode queryMode ) { + this.numberOfBids = numberOfBids; + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + int bidId = ThreadLocalRandom.current().nextInt( 1, numberOfBids + 1 ); + return new SelectRandomBidQuery( bidId, queryMode ); + } + + + private static class SelectRandomBidQuery extends Query { + + private final int bidId; + private final String tableName; + + + public SelectRandomBidQuery( int bidId, QueryMode queryMode ) { + super( EXPECT_RESULT ); + this.bidId = bidId; + + if ( queryMode.equals( QueryMode.VIEW ) ) { + tableName = "bid_view"; + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + tableName = "bid_materialized"; + } else { + tableName = "bid"; + } + } + + + @Override + public String getSql() { + return "SELECT * FROM " + tableName + " b WHERE b.id=" + bidId; + } + + + @Override + public String getParameterizedSqlQuery() { + return "SELECT * FROM " + tableName + " b WHERE b.id=?"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.INTEGER, bidId ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public." + tableName ) + .queryString( "public." + tableName + ".id", "=" + bidId ); + } + + + @Override + public String getMongoQl() { + return "db." + tableName + ".find({\"id\":" + bidId + "})"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectRandomUser.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectRandomUser.java new file mode 100644 index 00000000..e61c75d7 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectRandomUser.java @@ -0,0 +1,115 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; +import kong.unirest.HttpRequest; +import kong.unirest.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class SelectRandomUser extends QueryBuilder { + + private static final boolean EXPECT_RESULT = true; + + private final int numberOfUsers; + private final QueryMode queryMode; + + + public SelectRandomUser( int numberOfUsers, QueryMode queryMode ) { + this.numberOfUsers = numberOfUsers; + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + int userId = ThreadLocalRandom.current().nextInt( 1, numberOfUsers + 1 ); + return new SelectRandomUserQuery( userId, queryMode ); + } + + + private static class SelectRandomUserQuery extends Query { + + private final int userId; + private final String tableName; + + + public SelectRandomUserQuery( int userId, QueryMode queryMode ) { + super( EXPECT_RESULT ); + this.userId = userId; + + if ( queryMode.equals( QueryMode.VIEW ) ) { + tableName = "user_view"; + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + tableName = "user_materialized"; + } else { + tableName = "\"user\""; + } + } + + + @Override + public String getSql() { + return "SELECT * FROM " + tableName + " WHERE id=" + userId; + } + + + @Override + public String getParameterizedSqlQuery() { + return "SELECT * FROM " + tableName + " WHERE id=?"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.INTEGER, userId ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public." + tableName ) + .queryString( "public." + tableName + ".id", "=" + userId ); + } + + + @Override + public String getMongoQl() { + return "db." + tableName + ".find({\"id\":" + userId + "})"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectTheHundredNextEndingAuctionsOfRandomCategory.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectTheHundredNextEndingAuctionsOfRandomCategory.java new file mode 100644 index 00000000..bdea739e --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectTheHundredNextEndingAuctionsOfRandomCategory.java @@ -0,0 +1,166 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import com.devskiller.jfairy.Fairy; +import com.devskiller.jfairy.producer.DateProducer; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; +import kong.unirest.HttpRequest; +import kong.unirest.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; +import org.polypheny.simpleclient.scenario.gavelNG.GavelNGConfig; + + +public class SelectTheHundredNextEndingAuctionsOfRandomCategory extends QueryBuilder { + + private static final boolean EXPECT_RESULT = true; + + private final int numberOfCategories; + private final int auctionDateMaxYearsInPast; + + private final DateProducer dateProducer; + private final QueryMode queryMode; + + + public SelectTheHundredNextEndingAuctionsOfRandomCategory( int numberOfCategories, GavelNGConfig config, QueryMode queryMode ) { + this.numberOfCategories = numberOfCategories; + this.auctionDateMaxYearsInPast = config.auctionDateMaxYearsInPast; + this.dateProducer = Fairy.create().dateProducer(); + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + LocalDateTime date = dateProducer.randomDateInThePast( auctionDateMaxYearsInPast ); + date = date.withNano( 0 ); + int categoryId = ThreadLocalRandom.current().nextInt( 1, numberOfCategories + 1 ); + return new SelectTheHundredNextEndingAuctionsOfRandomCategoryQuery( date, categoryId, queryMode ); + } + + + private static class SelectTheHundredNextEndingAuctionsOfRandomCategoryQuery extends Query { + + private final LocalDateTime date; + private final int categoryId; + private final QueryMode queryMode; + + + public SelectTheHundredNextEndingAuctionsOfRandomCategoryQuery( LocalDateTime date, int categoryId, QueryMode queryMode ) { + super( EXPECT_RESULT ); + this.date = date; + this.categoryId = categoryId; + this.queryMode = queryMode; + } + + + @Override + public String getSql() { + if ( queryMode.equals( QueryMode.VIEW ) ) { + return "SELECT a.id, a.title, a.end_date FROM auctionCategory_view a WHERE a.category =" + categoryId + " AND " + + "a.end_date > timestamp '" + date.format( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" ) ) + "' ORDER BY end_date desc LIMIT 100"; + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return "SELECT a.id, a.title, a.end_date FROM auctionCategory_materialized a WHERE a.category =" + categoryId + " AND " + + "a.end_date > timestamp '" + date.format( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" ) ) + "' ORDER BY end_date desc LIMIT 100"; + } else { + return "SELECT a.id, a.title, a.end_date FROM auction a WHERE a.category =" + categoryId + " AND " + + "a.end_date > timestamp '" + date.format( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" ) ) + "' ORDER BY end_date desc LIMIT 100"; + } + } + + + @Override + public String getParameterizedSqlQuery() { + if ( queryMode.equals( QueryMode.VIEW ) ) { + return "SELECT a.id, a.title, a.end_date FROM auctionCategory_view a WHERE a.category=? AND " + + "a.end_date > timestamp '" + date.format( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" ) ) + "' ORDER BY end_date desc LIMIT 100"; + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return "SELECT a.id, a.title, a.end_date FROM auctionCategory_materialized a WHERE a.category=? AND " + + "a.end_date > timestamp '" + date.format( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" ) ) + "' ORDER BY end_date desc LIMIT 100"; + } else { + return "SELECT a.id, a.title, a.end_date FROM auction a WHERE a.category=? AND " + + "a.end_date > timestamp '" + date.format( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" ) ) + "' ORDER BY end_date desc LIMIT 100"; + } + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.INTEGER, categoryId ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + if ( queryMode.equals( QueryMode.VIEW ) ) { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public.auctionCategory_view" ) + .queryString( "_project", "public.auctionCategory_view.id,public.auctionCategory_view.title,public.auctionCategory_view.end_date" ) + .queryString( "public.auctionCategory_view.category", "=" + categoryId ) + .queryString( "public.auctionCategory_view.end_date", ">" + date.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME ) ) + .queryString( "_sort", "public.auctionCategory_view.end_date@DESC" ) + .queryString( "_limit", 100 ); + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public.auctionCategory_materialized" ) + .queryString( "_project", "public.auctionCategory_materialized.id,public.auctionCategory_materialized.title,public.auctionCategory_materialized.end_date" ) + .queryString( "public.auctionCategory_materialized.category", "=" + categoryId ) + .queryString( "public.auctionCategory_materialized.end_date", ">" + date.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME ) ) + .queryString( "_sort", "public.auctionCategory_materialized.end_date@DESC" ) + .queryString( "_limit", 100 ); + } else { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public.auction" ) + .queryString( "_project", "public.auction.id,public.auction.title,public.auction.end_date" ) + .queryString( "public.auction.category", "=" + categoryId ) + .queryString( "public.auction.end_date", ">" + date.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME ) ) + .queryString( "_sort", "public.auction.end_date@DESC" ) + .queryString( "_limit", 100 ); + } + + } + + + @Override + public String getMongoQl() { + return "db.auction.aggregate([" + + "{\"$match\":{\"category\":" + categoryId + ",\"end_date\":{\"$gt\":" + date.toLocalDate().toEpochDay() + "}}}," + + "{\"$sort\":{\"end_date\": -1}}," + + "{\"$project\":{\"id\":1,\"title\":1,\"end_date\":1}}," + + "{\"limit\": 100}" + + "])"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectTopHundredSellerByNumberOfAuctions.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectTopHundredSellerByNumberOfAuctions.java new file mode 100644 index 00000000..bcafead9 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectTopHundredSellerByNumberOfAuctions.java @@ -0,0 +1,108 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.HashMap; +import java.util.Map; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class SelectTopHundredSellerByNumberOfAuctions extends QueryBuilder { + + + private static final boolean EXPECT_RESULT = true; + private final QueryMode queryMode; + + + public SelectTopHundredSellerByNumberOfAuctions( QueryMode queryMode ) { + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + return new SelectTopHundredSellerByNumberOfAuctionsQuery( queryMode ); + } + + + private static class SelectTopHundredSellerByNumberOfAuctionsQuery extends Query { + + private final QueryMode queryMode; + + + public SelectTopHundredSellerByNumberOfAuctionsQuery( QueryMode queryMode ) { + super( EXPECT_RESULT ); + this.queryMode = queryMode; + } + + + @Override + public String getSql() { + if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + return "SELECT * FROM topHundredSellerByNumberOfAuctions_materialized LIMIT 100"; + } else if ( queryMode.equals( QueryMode.VIEW ) ) { + return "SELECT * FROM topHundredSellerByNumberOfAuctions_view LIMIT 100"; + } else { + return "SELECT u.last_name, u.first_name, count(a.id) as number " + + "FROM auction a INNER JOIN \"user\" u ON a.\"user\" = u.id " + + "GROUP BY a.\"user\", u.last_name, u.first_name " + + "ORDER BY number desc LIMIT 100"; + } + } + + + @Override + public String getParameterizedSqlQuery() { + return getSql(); + } + + + @Override + public Map> getParameterValues() { + return new HashMap<>(); + } + + + @Override + public HttpRequest getRest() { + return null; + } + + + @Override + public String getMongoQl() { + // $lookup not yet supported + return null; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectTopTenCitiesByNumberOfCustomers.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectTopTenCitiesByNumberOfCustomers.java new file mode 100644 index 00000000..8483cebd --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/SelectTopTenCitiesByNumberOfCustomers.java @@ -0,0 +1,113 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.HashMap; +import java.util.Map; +import kong.unirest.HttpRequest; +import kong.unirest.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class SelectTopTenCitiesByNumberOfCustomers extends QueryBuilder { + + private static final boolean EXPECT_RESULT = true; + private final QueryMode queryMode; + + + public SelectTopTenCitiesByNumberOfCustomers( QueryMode queryMode ) { + this.queryMode = queryMode; + } + + + @Override + public Query getNewQuery() { + return new SelectTopTenCitiesByNumberOfCustomersQuery( queryMode ); + } + + + private static class SelectTopTenCitiesByNumberOfCustomersQuery extends Query { + + private final String tableName; + + + public SelectTopTenCitiesByNumberOfCustomersQuery( QueryMode queryMode ) { + super( EXPECT_RESULT ); + + if ( queryMode.equals( QueryMode.VIEW ) ) { + tableName = "user_view"; + } else if ( queryMode.equals( QueryMode.MATERIALIZED ) ) { + tableName = "user_materialized"; + } else { + tableName = "\"user\""; + } + } + + + @Override + public String getSql() { + return "SELECT city, COUNT(city) as number FROM " + tableName + " GROUP BY city ORDER BY number desc LIMIT 10"; + } + + + @Override + public String getParameterizedSqlQuery() { + return getSql(); + } + + + @Override + public Map> getParameterValues() { + return new HashMap<>(); + } + + + @Override + public HttpRequest getRest() { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public.user" ) + .queryString( "_project", "public." + tableName + ".city@city,public." + tableName + ".city@number(COUNT)" ) + .queryString( "_groupby", "city" ) + .queryString( "_sort", "number@DESC" ) + .queryString( "_limit", 10 ); + } + + + @Override + public String getMongoQl() { + return "db." + tableName + ".aggregate([" + + "{\"$group\":{\"_id\":\"city\",\"number\": {\"$sum\": 1 }}}," + + "{\"$project\":{\"number\":1,\"city\":\"$_id\"}}," + + "{\"$sort\":{\"number\": -1 }}," + + "{\"$limit\":10}])"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncateAuction.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncateAuction.java new file mode 100644 index 00000000..e344c748 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncateAuction.java @@ -0,0 +1,85 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.Map; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class TruncateAuction extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + + + @Override + public Query getNewQuery() { + return new TruncateAuctionQuery(); + } + + + private static class TruncateAuctionQuery extends Query { + + public TruncateAuctionQuery() { + super( EXPECT_RESULT ); + } + + + @Override + public String getSql() { + return "TRUNCATE TABLE auction"; + } + + + @Override + public String getParameterizedSqlQuery() { + return null; + } + + + @Override + public Map> getParameterValues() { + return null; + } + + + @Override + public HttpRequest getRest() { + return null; + } + + + @Override + public String getMongoQl() { + return "db.auction.deleteMany({})"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncateBid.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncateBid.java new file mode 100644 index 00000000..cd87546f --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncateBid.java @@ -0,0 +1,85 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.Map; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class TruncateBid extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + + + @Override + public Query getNewQuery() { + return new TruncateBidQuery(); + } + + + private static class TruncateBidQuery extends Query { + + public TruncateBidQuery() { + super( EXPECT_RESULT ); + } + + + @Override + public String getSql() { + return "TRUNCATE TABLE bid"; + } + + + @Override + public String getParameterizedSqlQuery() { + return null; + } + + + @Override + public Map> getParameterValues() { + return null; + } + + + @Override + public HttpRequest getRest() { + return null; + } + + + @Override + public String getMongoQl() { + return "db.bid.deleteMany({})"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncateCategory.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncateCategory.java new file mode 100644 index 00000000..54b3e07a --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncateCategory.java @@ -0,0 +1,85 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.Map; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class TruncateCategory extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + + + @Override + public Query getNewQuery() { + return new TruncateCategoryQuery(); + } + + + private static class TruncateCategoryQuery extends Query { + + public TruncateCategoryQuery() { + super( EXPECT_RESULT ); + } + + + @Override + public String getSql() { + return "TRUNCATE TABLE category"; + } + + + @Override + public String getParameterizedSqlQuery() { + return null; + } + + + @Override + public Map> getParameterValues() { + return null; + } + + + @Override + public HttpRequest getRest() { + return null; + } + + + @Override + public String getMongoQl() { + return "db.category.deleteMany({})"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncateCondition.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncateCondition.java new file mode 100644 index 00000000..e765bf3a --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncateCondition.java @@ -0,0 +1,85 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.Map; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class TruncateCondition extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + + + @Override + public Query getNewQuery() { + return new TruncateConditionQuery(); + } + + + private static class TruncateConditionQuery extends Query { + + public TruncateConditionQuery() { + super( EXPECT_RESULT ); + } + + + @Override + public String getSql() { + return "TRUNCATE TABLE \"condition\""; + } + + + @Override + public String getParameterizedSqlQuery() { + return null; + } + + + @Override + public Map> getParameterValues() { + return null; + } + + + @Override + public HttpRequest getRest() { + return null; + } + + + @Override + public String getMongoQl() { + return "db.condition.deleteMany({})"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncatePicture.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncatePicture.java new file mode 100644 index 00000000..99ec1f0a --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncatePicture.java @@ -0,0 +1,85 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.Map; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class TruncatePicture extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + + + @Override + public Query getNewQuery() { + return new TruncatePictureQuery(); + } + + + private static class TruncatePictureQuery extends Query { + + public TruncatePictureQuery() { + super( EXPECT_RESULT ); + } + + + @Override + public String getSql() { + return "TRUNCATE TABLE picture"; + } + + + @Override + public String getParameterizedSqlQuery() { + return null; + } + + + @Override + public Map> getParameterValues() { + return null; + } + + + @Override + public HttpRequest getRest() { + return null; + } + + + @Override + public String getMongoQl() { + return "db.picture.deleteMany({})"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncateUser.java b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncateUser.java new file mode 100644 index 00000000..6da0c78d --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/gavelNG/queryBuilder/TruncateUser.java @@ -0,0 +1,85 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2022 The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package org.polypheny.simpleclient.scenario.gavelNG.queryBuilder; + + +import java.util.Map; +import kong.unirest.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + + +public class TruncateUser extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + + + @Override + public Query getNewQuery() { + return new TruncateUserQuery(); + } + + + private static class TruncateUserQuery extends Query { + + public TruncateUserQuery() { + super( EXPECT_RESULT ); + } + + + @Override + public String getSql() { + return "TRUNCATE TABLE \"user\""; + } + + + @Override + public String getParameterizedSqlQuery() { + return null; + } + + + @Override + public Map> getParameterValues() { + return null; + } + + + @Override + public HttpRequest getRest() { + return null; + } + + + @Override + public String getMongoQl() { + return "db.\"user\".deleteMany({})"; + } + + } + +} diff --git a/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/conditions.txt b/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/conditions.txt new file mode 100644 index 00000000..d2d58277 --- /dev/null +++ b/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/conditions.txt @@ -0,0 +1,5 @@ +New +As good as new +Used +Antique +Defect diff --git a/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/gavelNG.properties b/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/gavelNG.properties new file mode 100644 index 00000000..4b66ce35 --- /dev/null +++ b/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/gavelNG.properties @@ -0,0 +1,36 @@ +scenario = "gavelNG" + +numberOfThreads = 4 +numberOfWarmUpIterations = 4 +progressReportBase = 100 + +# Data Generation +numberOfCategories = 35 +numberOfConditions = 5 +numberOfUsers = 1000 +numberOfAuctions = 1000 + +auctionTitleMinLength=2 +auctionTitleMaxLength=8 + +auctionDescriptionMinLength=5 +auctionDescriptionMaxLength=15 + +auctionDateMaxYearsInPast = 4 +auctionNumberOfDays = 10 + +minNumberOfBidsPerAuction = 30 +maxNumberOfBidsPerAuction = 200 + +minNumberOfPicturesPerAuction = 1 +maxNumberOfPicturesPerAuction = 6 + +maxBatchSize = 1000 +usePreparedBatchForDataInsertion = true + +numberOfUserGenerationThreads = 2 +numberOfAuctionGenerationThreads = 2 +parallelizeUserGenerationAndAuctionGeneration = false + +queryMode = Table + diff --git a/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/gavelNGProfile.properties b/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/gavelNGProfile.properties new file mode 100644 index 00000000..e6aab3c4 --- /dev/null +++ b/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/gavelNGProfile.properties @@ -0,0 +1,32 @@ +scenario = "gavelNGProfile" + +# initial data stores +dataStores = "mongodb,hsqldb" + +# which store for which table +storeForTable = "user-mongodb,bid-hsqldb,picture-hsqldb,auction-mongodb,category-hsqldb" + +# schedule to warmup +warmup = "sql-s,mql-s,sql-i,mql-i,sql-c,mql-c" + +# schedule +schedules = "sql-i3d30,mql-s700d0,sql-c1d60,sql-c1000d0,sql-u5d0,mql-s70d0,sql-c1d20,sql-i3d30,sql-c1d60,sql-c100d0,sql-u5d0,mql-s70d0,sql-c1d20,sql-s3000d0" + + + +/////////////////////////////////INFORMATION//////////////////////////////// +# i = insert +# s = simple select +# c = complex select +# u = update +# d = delete +# t = truncate + +# d = delay + +# number after query type -> how often a query from this type is used +# number after delay -> delay in seconds after those queries +# if more than one threads is used, it only stops the thread responsible for this query + + + diff --git a/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/materialized.sql b/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/materialized.sql new file mode 100644 index 00000000..4ced2dd0 --- /dev/null +++ b/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/materialized.sql @@ -0,0 +1,15 @@ +CREATE MATERIALIZED VIEW "user_materialized" AS SELECT * FROM "user" FRESHNESS MANUAL +CREATE MATERIALIZED VIEW "bid_materialized" AS SELECT * FROM "bid" FRESHNESS MANUAL +CREATE MATERIALIZED VIEW "picture_materialized" AS SELECT * FROM "picture" FRESHNESS MANUAL +CREATE MATERIALIZED VIEW "auction_materialized" AS SELECT * FROM "auction" FRESHNESS MANUAL +CREATE MATERIALIZED VIEW "category_materialized" AS SELECT * FROM "category" FRESHNESS MANUAL +CREATE MATERIALIZED VIEW "countAuction_materialized" AS SELECT count(*) as "NUMBER" FROM "auction" FRESHNESS MANUAL +CREATE MATERIALIZED VIEW "countBid_materialized" AS SELECT count(*) as "NUMBER" FROM "bid" FRESHNESS MANUAL +CREATE MATERIALIZED VIEW "auctionCategory_materialized" AS SELECT "id", "title", "category", "end_date" FROM "auction" FRESHNESS MANUAL +CREATE MATERIALIZED VIEW "topHundredSellerByNumberOfAuctions_materialized" AS SELECT u.last_name, u.first_name, count(a.id) as number FROM auction a INNER JOIN "user" u ON a."user" = u.id GROUP BY a."user", u.last_name, u.first_name ORDER BY number desc Limit 100 FRESHNESS MANUAL +CREATE MATERIALIZED VIEW "highestBid_materialized" AS SELECT "last_name", "first_name" FROM "user" WHERE "user"."id" = (SELECT highest.highestUser FROM (SELECT "bid"."user" as highestUser, MAX("bid"."amount") FROM "bid" GROUP BY "bid"."user" ORDER BY MAX("bid"."amount") DESC) as highest Limit 1) FRESHNESS MANUAL +CREATE MATERIALIZED VIEW "priceBetween_materialized" AS SELECT "auction"."title", "bid"."amount" FROM "auction", "bid" WHERE "bid"."auction" = "auction"."id" AND "bid"."amount" > 10 AND "bid"."amount" < 1000000 ORDER BY "bid"."amount" DESC Limit 100 FRESHNESS MANUAL +CREATE MATERIALIZED VIEW "otherInterestingActiveAuctions_materialized" SELECT c.last_name,a.title, a.end_date FROM (SELECT "public"."user"."last_name" as "last_name", "public"."user"."id" as "userid","public"."auction"."category" as "categoryid", "public"."auction"."condition" as "conditionid" FROM "public"."user","public"."auction" WHERE "public"."auction"."user" = "public"."user"."id" AND "public"."auction"."end_date" < CURRENT_TIMESTAMP Limit 1) as "c", "public"."auction" as "a" WHERE (c.categoryid = a.category AND c.conditionid = a."condition") AND a.end_date > CURRENT_TIMESTAMP Limit 100 FRESHNESS MANUAL +CREATE MATERIALIZED VIEW "differenceBetweenLowestAndHighestBid_materialized" SELECT difference, title, b.auctionid, c.auctionid FROM (SELECT (a.maxamount - a.minamount) as difference, a.auctionid as auctionid FROM (SELECT min("public"."bid"."amount") as "minamount", max("public"."bid"."amount") as "maxamount", "public"."bid"."auction" as "auctionid" FROM "public"."bid" WHERE "public"."bid"."auction" in ( SELECT "public"."auction"."id" FROM "public"."auction" ) Group by "public"."bid"."auction") as "a")as "b" join (SELECT "public"."auction"."title" as "title", "public"."auction"."id" as "auctionid" FROM "public"."auction") as "c" on b.auctionid = c.auctionid GROUP BY title, b.auctionid, c.auctionid, difference LIMIT 100 FRESHNESS MANUAL +CREATE MATERIALIZED VIEW "allActiveAuctions_materialized" SELECT "public"."auction"."title", "public"."auction"."end_date" FROM "public"."auction" WHERE "public"."auction"."end_date" > CURRENT_TIMESTAMP FRESHNESS MANUAL +CREATE MATERIALIZED VIEW "maxAmountConditionFinishedAuctions_materialized" SELECT b."maxamount", "d"."condition" FROM (SELECT a."maxamount", "c"."condition" FROM (SELECT max("public"."bid"."amount") as "maxamount", "public"."bid"."auction" as "auctionid" FROM "public"."bid" WHERE "public"."bid"."auction" in ( SELECT "public"."auction"."id" FROM "public"."auction" WHERE "end_date" < CURRENT_TIMESTAMP) Group by "public"."bid"."auction") as "a" INNER JOIN "public"."auction" as "c" ON a.auctionid = "c"."id") as "b" INNER JOIN "public"."condition" as "d" ON "b"."condition" = d."id" FRESHNESS MANUAL \ No newline at end of file diff --git a/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/schema.mongoql b/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/schema.mongoql new file mode 100644 index 00000000..dca1024a --- /dev/null +++ b/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/schema.mongoql @@ -0,0 +1,6 @@ +"user" +"bid" +"picture" +"auction" +"category" +"condition" \ No newline at end of file diff --git a/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/schema.sql b/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/schema.sql new file mode 100644 index 00000000..dfa91092 --- /dev/null +++ b/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/schema.sql @@ -0,0 +1,12 @@ +CREATE TABLE "user" ( "id" integer NOT NULL, "email" varchar(100) NOT NULL, "password" varchar(100) NOT NULL, "last_name" varchar(50) NOT NULL, "first_name" varchar(50) NOT NULL, "gender" varchar(1) NOT NULL, "birthday" date NOT NULL, "city" varchar(50) NOT NULL, "zip_code" varchar(20) NOT NULL, "country" varchar(50) NOT NULL, primary key ("id") ) +CREATE TABLE "bid" ( "id" integer NOT NULL, "amount" integer NOT NULL, "timestamp" timestamp NOT NULL, "user" integer NOT NULL, "auction" integer NOT NULL, primary key ("id") ) +CREATE TABLE "picture" ( "filename" varchar(50) NOT NULL, "type" varchar(20) NOT NULL, "size" integer NOT NULL, "auction" integer NOT NULL, primary key ("filename") ) +CREATE TABLE "auction" ( "id" integer NOT NULL, "title" varchar(100) NOT NULL, "description" varchar(2500) NOT NULL, "start_date" timestamp NOT NULL, "end_date" timestamp NOT NULL, "category" integer NOT NULL, "user" integer NOT NULL, "condition" integer NOT NULL, primary key ("id") ) +CREATE TABLE "category" ( "id" integer NOT NULL, "name" varchar(100) NOT NULL, primary key ("id") ) +CREATE TABLE "condition" ("id" integer NOT NULL, "condition" varchar(100) NOT NULL, primary key ("id") ) +ALTER TABLE "bid" ADD CONSTRAINT "fk_bid_user" FOREIGN KEY ( "user" ) REFERENCES "user"("id") +ALTER TABLE "bid" ADD CONSTRAINT "fk_bid_auction" FOREIGN KEY ( "auction" ) REFERENCES "auction"("id") +ALTER TABLE "picture" ADD CONSTRAINT "fk_picture_auction" FOREIGN KEY ( "auction" ) REFERENCES "auction"("id") +ALTER TABLE "auction" ADD CONSTRAINT "fk_auction_category" FOREIGN KEY ( "category" ) REFERENCES "category"("id") +ALTER TABLE "auction" ADD CONSTRAINT "fk_auction_user" FOREIGN KEY ( "user" ) REFERENCES "user"("id") +ALTER TABLE "auction" ADD CONSTRAINT "fk_auction_condition" FOREIGN KEY ( "condition" ) REFERENCES "condition"("id") \ No newline at end of file diff --git a/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/view.sql b/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/view.sql new file mode 100644 index 00000000..943b8c1a --- /dev/null +++ b/src/main/resources/org/polypheny/simpleclient/scenario/gavelNG/view.sql @@ -0,0 +1,15 @@ +CREATE VIEW "user_view" AS SELECT * FROM "user" +CREATE VIEW "bid_view" AS SELECT * FROM "bid" +CREATE VIEW "picture_view" AS SELECT * FROM "picture" +CREATE VIEW "auction_view" AS SELECT * FROM "auction" +CREATE VIEW "category_view" AS SELECT * FROM "category" +CREATE VIEW "countAuction" AS SELECT count(*) as "NUMBER" FROM "auction" +CREATE VIEW "countBid" AS SELECT count(*) as "NUMBER" FROM "bid" +CREATE VIEW "auctionCategory_view" AS SELECT "id", "title", "end_date", "category" FROM "auction" +CREATE VIEW topHundredSellerByNumberOfAuctions_view AS SELECT u.last_name, u.first_name, count(a.id) as number FROM auction a INNER JOIN "user" u ON a."user" = u.id GROUP BY a."user", u.last_name, u.first_name ORDER BY number desc Limit 100 +CREATE VIEW highestBid_view AS SELECT "last_name", "first_name" FROM "user" WHERE "user"."id" = (SELECT highest.highestUser FROM (SELECT "bid"."user" as highestUser, MAX("bid"."amount") FROM "bid" GROUP BY "bid"."user" ORDER BY MAX("bid"."amount") DESC) as highest Limit 1) +CREATE VIEW "priceBetween_view" AS SELECT "auction"."title", "bid"."amount" FROM "auction", "bid" WHERE "bid"."auction" = "auction"."id" AND "bid"."amount" > 10 AND "bid"."amount" < 1000000 ORDER BY "bid"."amount" DESC Limit 100 +CREATE VIEW "otherInterestingActiveAuctions_view" SELECT c.last_name,a.title, a.end_date FROM (SELECT "public"."user"."last_name" as "last_name", "public"."user"."id" as "userid","public"."auction"."category" as "categoryid", "public"."auction"."condition" as "conditionid" FROM "public"."user","public"."auction" WHERE "public"."auction"."user" = "public"."user"."id" AND "public"."auction"."end_date" < CURRENT_TIMESTAMP Limit 1) as "c", "public"."auction" as "a" WHERE (c.categoryid = a.category AND c.conditionid = a."condition") AND a.end_date > CURRENT_TIMESTAMP Limit 100 +CREATE VIEW "differenceBetweenLowestAndHighestBid_view" SELECT difference, title, b.auctionid, c.auctionid FROM (SELECT (a.maxamount - a.minamount) as difference, a.auctionid as auctionid FROM (SELECT min("public"."bid"."amount") as "minamount", max("public"."bid"."amount") as "maxamount", "public"."bid"."auction" as "auctionid" FROM "public"."bid" WHERE "public"."bid"."auction" in ( SELECT "public"."auction"."id" FROM "public"."auction" ) Group by "public"."bid"."auction") as "a")as "b" join (SELECT "public"."auction"."title" as "title", "public"."auction"."id" as "auctionid" FROM "public"."auction") as "c" on b.auctionid = c.auctionid GROUP BY title, b.auctionid, c.auctionid, difference LIMIT 100 +CREATE VIEW "allActiveAuctions_view" SELECT "public"."auction"."title", "public"."auction"."end_date" FROM "public"."auction" WHERE "public"."auction"."end_date" > CURRENT_TIMESTAMP +CREATE VIEW "maxAmountConditionFinishedAuctions_view" SELECT b."maxamount", "d"."condition" FROM (SELECT a."maxamount", "c"."condition" FROM (SELECT max("public"."bid"."amount") as "maxamount", "public"."bid"."auction" as "auctionid" FROM "public"."bid" WHERE "public"."bid"."auction" in ( SELECT "public"."auction"."id" FROM "public"."auction" WHERE "end_date" < CURRENT_TIMESTAMP) Group by "public"."bid"."auction") as "a" INNER JOIN "public"."auction" as "c" ON a.auctionid = "c"."id") as "b" INNER JOIN "public"."condition" as "d" ON "b"."condition" = d."id" \ No newline at end of file