From 15ad6137cb05b7d748be0072ee93d454a2e612ec Mon Sep 17 00:00:00 2001 From: Rana B <120142163+ranaalotaibiMS@users.noreply.github.com> Date: Sat, 15 Feb 2025 00:01:47 +0300 Subject: [PATCH] Introduce session setup (#422) This PR introduces functionality for configuring a session by executing predefined statements before the benchmark execution begins. Users should specify the file containing these statements within the tag ` ` in the benchmarks' config files. CC: @bpkroth For example, ```xml sqlserver ... config/sqlserver/session_setup_sqlserver_cmds_example.sql ... ``` See Also: #192 --------- Co-authored-by: Rana Alotaibi Co-authored-by: Rana Alotaibi Co-authored-by: Brian Kroth Co-authored-by: Brian Kroth --- .github/workflows/maven.yml | 7 ++ config/sqlserver/sample_noop_config.xml | 4 + config/sqlserver/sample_tpch_config.xml | 2 + .../session_setup_sqlserver_cmds_example.sql | 4 + docker/sqlserver-latest/up.sh | 3 + .../java/com/oltpbenchmark/DBWorkload.java | 5 ++ .../oltpbenchmark/WorkloadConfiguration.java | 23 +++++- .../oltpbenchmark/api/BenchmarkModule.java | 4 + .../java/com/oltpbenchmark/api/Worker.java | 36 ++++++++ .../monitoring/SQLServerMonitor.java | 3 +- .../java/com/oltpbenchmark/util/FileUtil.java | 11 +++ .../resources/benchmarks/noop/ddl-generic.sql | 4 + .../oltpbenchmark/api/AbstractTestCase.java | 16 ++++ .../oltpbenchmark/api/AbstractTestLoader.java | 1 - .../oltpbenchmark/api/AbstractTestWorker.java | 10 ++- .../benchmarks/noop/TestNoOpLoader.java | 2 +- .../benchmarks/noop/TestNoOpWorker.java | 41 ++++++++++ .../TestNoOpWorkerWithSessionSetupFile.java | 82 +++++++++++++++++++ .../noop/sessionSetupFile-hsqldb.sql | 3 + 19 files changed, 254 insertions(+), 7 deletions(-) create mode 100644 config/sqlserver/session_setup_sqlserver_cmds_example.sql create mode 100644 src/test/java/com/oltpbenchmark/benchmarks/noop/TestNoOpWorkerWithSessionSetupFile.java create mode 100644 src/test/resources/benchmarks/noop/sessionSetupFile-hsqldb.sql diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 98cedbb35..96feff39b 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -689,6 +689,13 @@ jobs: entrypoint: /opt/mssql-tools/bin/sqlcmd args: -U sa -P SApassword1 -S sqlserver -b -Q "USE benchbase; CREATE USER benchuser01 FROM LOGIN benchuser01; EXEC sp_addrolemember 'db_owner', 'benchuser01';" + - name: Setup privileged access for monitoring and session start tests + uses: docker://mcr.microsoft.com/mssql-tools:latest + with: + entrypoint: /opt/mssql-tools/bin/sqlcmd + args: -U sa -P SApassword1 -S sqlserver -b -Q "USE master; GRANT ALTER SERVER STATE, VIEW SERVER PERFORMANCE STATE to benchuser01;" + + - name: Run benchmark # Note: user/pass should match those used in sample configs. run: | diff --git a/config/sqlserver/sample_noop_config.xml b/config/sqlserver/sample_noop_config.xml index 53cfc54f0..8db7cd4bb 100644 --- a/config/sqlserver/sample_noop_config.xml +++ b/config/sqlserver/sample_noop_config.xml @@ -11,6 +11,10 @@ TRANSACTION_SERIALIZABLE 128 + + + config/sqlserver/session_setup_sqlserver_cmds_example.sql + 1 diff --git a/config/sqlserver/sample_tpch_config.xml b/config/sqlserver/sample_tpch_config.xml index 153ba83de..2cefff63b 100644 --- a/config/sqlserver/sample_tpch_config.xml +++ b/config/sqlserver/sample_tpch_config.xml @@ -10,6 +10,8 @@ true TRANSACTION_SERIALIZABLE 1024 + + 0.1 diff --git a/config/sqlserver/session_setup_sqlserver_cmds_example.sql b/config/sqlserver/session_setup_sqlserver_cmds_example.sql new file mode 100644 index 000000000..c52504ad2 --- /dev/null +++ b/config/sqlserver/session_setup_sqlserver_cmds_example.sql @@ -0,0 +1,4 @@ +-- SQL Server Database Console Command statements (DBCC) +-- NOTE: Requires "ALTER SERVER STATE" permission +DBCC DROPCLEANBUFFERS -- clear buffers (for cold runs) +DBCC FREEPROCCACHE -- clean plan cache \ No newline at end of file diff --git a/docker/sqlserver-latest/up.sh b/docker/sqlserver-latest/up.sh index 77c98c3ab..dbb7cbe15 100755 --- a/docker/sqlserver-latest/up.sh +++ b/docker/sqlserver-latest/up.sh @@ -38,3 +38,6 @@ run_sqlcmd_in_docker -Q "CREATE LOGIN benchuser01 WITH PASSWORD='P@ssw0rd';" || # Setup access run_sqlcmd_in_docker -Q "USE benchbase; CREATE USER benchuser01 FROM LOGIN benchuser01; EXEC sp_addrolemember 'db_owner', 'benchuser01';" || true + +# Setup privileged access for monitoring and session start tests +run_sqlcmd_in_docker -Q "USE master; GRANT ALTER SERVER STATE, VIEW SERVER PERFORMANCE STATE TO benchuser01;" || true diff --git a/src/main/java/com/oltpbenchmark/DBWorkload.java b/src/main/java/com/oltpbenchmark/DBWorkload.java index 0c2ddc5cb..11ab05ca0 100644 --- a/src/main/java/com/oltpbenchmark/DBWorkload.java +++ b/src/main/java/com/oltpbenchmark/DBWorkload.java @@ -138,6 +138,7 @@ public static void main(String[] args) throws Exception { wrkld.setPassword(xmlConfig.getString("password")); wrkld.setRandomSeed(xmlConfig.getInt("randomSeed", -1)); wrkld.setBatchSize(xmlConfig.getInt("batchsize", 128)); + wrkld.setSessionSetupFile(xmlConfig.getString("sessionsetupfile")); wrkld.setMaxRetries(xmlConfig.getInt("retries", 3)); wrkld.setNewConnectionPerTxn(xmlConfig.getBoolean("newConnectionPerTxn", false)); wrkld.setReconnectOnConnectionFailure( @@ -196,6 +197,9 @@ public static void main(String[] args) throws Exception { initDebug.put("URL", wrkld.getUrl()); initDebug.put("Isolation", wrkld.getIsolationString()); initDebug.put("Batch Size", wrkld.getBatchSize()); + initDebug.put("DDL Path", wrkld.getDDLPath()); + initDebug.put("Loader Threads", wrkld.getLoaderThreads()); + initDebug.put("Session Setup File", wrkld.getSessionSetupFile()); initDebug.put("Scale Factor", wrkld.getScaleFactor()); initDebug.put("Terminals", wrkld.getTerminals()); initDebug.put("New Connection Per Txn", wrkld.getNewConnectionPerTxn()); @@ -247,6 +251,7 @@ public static void main(String[] args) throws Exception { if (xmlConfig.containsKey("afterload")) { bench.setAfterLoadScriptPath(xmlConfig.getString("afterload")); } + initDebug.put("After Load Script", bench.getAfterLoadScriptPath()); TransactionType tmpType = bench.initTransactionType( diff --git a/src/main/java/com/oltpbenchmark/WorkloadConfiguration.java b/src/main/java/com/oltpbenchmark/WorkloadConfiguration.java index 5ace0362c..5914eb6f5 100644 --- a/src/main/java/com/oltpbenchmark/WorkloadConfiguration.java +++ b/src/main/java/com/oltpbenchmark/WorkloadConfiguration.java @@ -17,7 +17,9 @@ import com.oltpbenchmark.api.TransactionTypes; import com.oltpbenchmark.types.DatabaseType; +import com.oltpbenchmark.util.FileUtil; import com.oltpbenchmark.util.ThreadUtil; +import java.io.FileNotFoundException; import java.sql.Connection; import java.util.ArrayList; import java.util.List; @@ -33,6 +35,7 @@ public class WorkloadConfiguration { private String password; private String driverClass; private int batchSize; + private String sessionSetupFile; private int maxRetries; private int randomSeed = -1; private double scaleFactor = 1.0; @@ -120,6 +123,14 @@ public void setBatchSize(int batchSize) { this.batchSize = batchSize; } + public String getSessionSetupFile() { + return sessionSetupFile; + } + + public void setSessionSetupFile(String sessionSetupFile) throws FileNotFoundException { + this.sessionSetupFile = FileUtil.checkPath(sessionSetupFile, "sessionsetupfile"); + } + public int getMaxRetries() { return maxRetries; } @@ -292,8 +303,8 @@ public String getDDLPath() { } /** Set the path in which we can find the ddl script. */ - public void setDDLPath(String ddlPath) { - this.ddlPath = ddlPath; + public void setDDLPath(String ddlPath) throws FileNotFoundException { + this.ddlPath = FileUtil.checkPath(ddlPath, "ddlpath"); } /** A utility method that init the phaseIterator and dialectMap */ @@ -394,8 +405,16 @@ public String toString() { + ", driverClass='" + driverClass + '\'' + + ", reconnectOnFailure=" + + reconnectOnConnectionFailure + + ", newConnectionPerTxn=" + + newConnectionPerTxn + ", batchSize=" + batchSize + + ", ddlpath=" + + ddlPath + + ", sessionSetupFile=" + + sessionSetupFile + ", maxRetries=" + maxRetries + ", scaleFactor=" diff --git a/src/main/java/com/oltpbenchmark/api/BenchmarkModule.java b/src/main/java/com/oltpbenchmark/api/BenchmarkModule.java index 989d6eb9a..193151ccb 100644 --- a/src/main/java/com/oltpbenchmark/api/BenchmarkModule.java +++ b/src/main/java/com/oltpbenchmark/api/BenchmarkModule.java @@ -93,6 +93,10 @@ public final void setAfterLoadScriptPath(String scriptPath) { this.afterLoadScriptPath = scriptPath; } + public String getAfterLoadScriptPath() { + return this.afterLoadScriptPath; + } + // -------------------------------------------------------------------------- // IMPLEMENTING CLASS INTERFACE // -------------------------------------------------------------------------- diff --git a/src/main/java/com/oltpbenchmark/api/Worker.java b/src/main/java/com/oltpbenchmark/api/Worker.java index 3cac3882d..e50cbcea6 100644 --- a/src/main/java/com/oltpbenchmark/api/Worker.java +++ b/src/main/java/com/oltpbenchmark/api/Worker.java @@ -26,6 +26,9 @@ import com.oltpbenchmark.types.TransactionStatus; import com.oltpbenchmark.util.Histogram; import com.oltpbenchmark.util.SQLUtil; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLRecoverableException; @@ -188,6 +191,13 @@ public final void run() { // In case of reuse reset the measurements latencies = new LatencyRecord(workloadState.getTestStartNs()); + // Invoke setup session + try { + this.setupSession(); + } catch (Throwable ex) { + throw new RuntimeException("Unexpected error when setting up the session " + this, ex); + } + // Invoke initialize callback try { this.initialize(); @@ -723,6 +733,32 @@ protected void initialize() { // The default is to do nothing } + /** + * Set up the session by running a set of statements before benchmark execution begins. The path + * of the file where a set of statements defined should be added in <sessionsetupfile> + * </sessionsetupfile> + */ + protected void setupSession() { + try { + String setupSessionFile = configuration.getSessionSetupFile(); + if (setupSessionFile == null || setupSessionFile.isEmpty()) { + return; + } + + String statements = new String(Files.readAllBytes(Paths.get(setupSessionFile))); + if (statements.isEmpty()) { + return; + } + + try (Statement stmt = conn.createStatement()) { + stmt.execute(statements); + } + // conn.commit(); + } catch (SQLException | IOException ex) { + throw new RuntimeException("Failed setting up session", ex); + } + } + /** * Invoke a single transaction for the given TransactionType * diff --git a/src/main/java/com/oltpbenchmark/api/collectors/monitoring/SQLServerMonitor.java b/src/main/java/com/oltpbenchmark/api/collectors/monitoring/SQLServerMonitor.java index d3d9143f1..fbff7b81b 100644 --- a/src/main/java/com/oltpbenchmark/api/collectors/monitoring/SQLServerMonitor.java +++ b/src/main/java/com/oltpbenchmark/api/collectors/monitoring/SQLServerMonitor.java @@ -21,7 +21,8 @@ /** * Implementation of a monitor specific to SQLServer. Uses SQLServer's system tables to extract - * relevant query and system information. + * relevant query and system information. Note: Requires "VIEW SERVER PERFORMANCE STATE" + * permissions. */ public class SQLServerMonitor extends DatabaseMonitor { diff --git a/src/main/java/com/oltpbenchmark/util/FileUtil.java b/src/main/java/com/oltpbenchmark/util/FileUtil.java index aa4c4eabd..13c47fa53 100644 --- a/src/main/java/com/oltpbenchmark/util/FileUtil.java +++ b/src/main/java/com/oltpbenchmark/util/FileUtil.java @@ -18,6 +18,7 @@ package com.oltpbenchmark.util; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.util.regex.Pattern; @@ -83,6 +84,16 @@ public static boolean exists(String path) { return (new File(path).exists()); } + public static String checkPath(String path, String name) throws FileNotFoundException { + if (path != null) path = path.trim(); + if (path == null || path.isEmpty()) return null; + + if (!FileUtil.exists(path)) { + throw new FileNotFoundException(name + " not found:" + path); + } + return path; + } + /** * Create any directory in the list paths if it doesn't exist * diff --git a/src/main/resources/benchmarks/noop/ddl-generic.sql b/src/main/resources/benchmarks/noop/ddl-generic.sql index d5d7a476f..e738f3201 100644 --- a/src/main/resources/benchmarks/noop/ddl-generic.sql +++ b/src/main/resources/benchmarks/noop/ddl-generic.sql @@ -1,4 +1,8 @@ DROP TABLE IF EXISTS FAKE; CREATE TABLE FAKE ( ID INT PRIMARY KEY +); +DROP TABLE IF EXISTS FAKE2; +CREATE TABLE FAKE2 ( + ID INT ); \ No newline at end of file diff --git a/src/test/java/com/oltpbenchmark/api/AbstractTestCase.java b/src/test/java/com/oltpbenchmark/api/AbstractTestCase.java index 37e42ebfa..37593ac59 100644 --- a/src/test/java/com/oltpbenchmark/api/AbstractTestCase.java +++ b/src/test/java/com/oltpbenchmark/api/AbstractTestCase.java @@ -68,6 +68,7 @@ public abstract class AbstractTestCase { protected final boolean createDatabase; protected final boolean loadDatabase; protected final String ddlOverridePath; + protected final String sessionSetupFile; private static final AtomicInteger portCounter = new AtomicInteger(9001); private static final int MAX_PORT_NUMBER = 65535; @@ -77,6 +78,7 @@ public AbstractTestCase(boolean createDatabase, boolean loadDatabase) { this.createDatabase = createDatabase; this.loadDatabase = loadDatabase; this.ddlOverridePath = null; + this.sessionSetupFile = null; } public AbstractTestCase(boolean createDatabase, boolean loadDatabase, String ddlOverridePath) { @@ -84,6 +86,19 @@ public AbstractTestCase(boolean createDatabase, boolean loadDatabase, String ddl this.createDatabase = createDatabase; this.loadDatabase = loadDatabase; this.ddlOverridePath = ddlOverridePath; + this.sessionSetupFile = null; + } + + public AbstractTestCase( + boolean createDatabase, + boolean loadDatabase, + String ddlOverridePath, + String sessionSetupFile) { + this.benchmark = null; + this.createDatabase = createDatabase; + this.loadDatabase = loadDatabase; + this.ddlOverridePath = ddlOverridePath; + this.sessionSetupFile = sessionSetupFile; } public abstract List> procedures(); @@ -127,6 +142,7 @@ public final void setUp() throws Exception { this.workConf.setBenchmarkName( BenchmarkModule.convertBenchmarkClassToBenchmarkName(benchmarkClass())); this.workConf.setDDLPath(this.ddlOverridePath); + this.workConf.setSessionSetupFile(this.sessionSetupFile); customWorkloadConfiguration(this.workConf); diff --git a/src/test/java/com/oltpbenchmark/api/AbstractTestLoader.java b/src/test/java/com/oltpbenchmark/api/AbstractTestLoader.java index 72b6ad7f8..83f8e88a8 100644 --- a/src/test/java/com/oltpbenchmark/api/AbstractTestLoader.java +++ b/src/test/java/com/oltpbenchmark/api/AbstractTestLoader.java @@ -17,7 +17,6 @@ package com.oltpbenchmark.api; import static org.junit.Assert.*; -import static org.junit.Assert.fail; import com.oltpbenchmark.catalog.Table; import com.oltpbenchmark.util.Histogram; diff --git a/src/test/java/com/oltpbenchmark/api/AbstractTestWorker.java b/src/test/java/com/oltpbenchmark/api/AbstractTestWorker.java index e96ecf333..9983be67e 100644 --- a/src/test/java/com/oltpbenchmark/api/AbstractTestWorker.java +++ b/src/test/java/com/oltpbenchmark/api/AbstractTestWorker.java @@ -41,6 +41,10 @@ public AbstractTestWorker(String ddlOverridePath) { super(true, true, ddlOverridePath); } + public AbstractTestWorker(String ddlOverridePath, String sessionSetupFile) { + super(true, true, ddlOverridePath, sessionSetupFile); + } + @Override public List ignorableTables() { return null; @@ -67,12 +71,14 @@ public void testGetProcedure() { } } - /** testExecuteWork */ + /* testExecuteWork + * Similar to Worker.run() + */ @Test public void testExecuteWork() throws Exception { - Worker w = workers.get(0); assertNotNull(w); + w.setupSession(); w.initialize(); assertFalse(this.conn.isReadOnly()); for (TransactionType txnType : this.workConf.getTransTypes()) { diff --git a/src/test/java/com/oltpbenchmark/benchmarks/noop/TestNoOpLoader.java b/src/test/java/com/oltpbenchmark/benchmarks/noop/TestNoOpLoader.java index 9498e3d4c..39306fd93 100644 --- a/src/test/java/com/oltpbenchmark/benchmarks/noop/TestNoOpLoader.java +++ b/src/test/java/com/oltpbenchmark/benchmarks/noop/TestNoOpLoader.java @@ -34,6 +34,6 @@ public Class benchmarkClass() { @Override public List ignorableTables() { - return List.of("FAKE"); + return List.of("FAKE", "FAKE2"); } } diff --git a/src/test/java/com/oltpbenchmark/benchmarks/noop/TestNoOpWorker.java b/src/test/java/com/oltpbenchmark/benchmarks/noop/TestNoOpWorker.java index c03339f20..a43c1cb68 100644 --- a/src/test/java/com/oltpbenchmark/benchmarks/noop/TestNoOpWorker.java +++ b/src/test/java/com/oltpbenchmark/benchmarks/noop/TestNoOpWorker.java @@ -16,9 +16,21 @@ package com.oltpbenchmark.benchmarks.noop; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + import com.oltpbenchmark.api.AbstractTestWorker; +import com.oltpbenchmark.api.BenchmarkModule; import com.oltpbenchmark.api.Procedure; +import com.oltpbenchmark.api.Worker; +import com.oltpbenchmark.catalog.Table; +import com.oltpbenchmark.util.SQLUtil; +import java.sql.ResultSet; +import java.sql.Statement; import java.util.List; +import org.junit.Test; public class TestNoOpWorker extends AbstractTestWorker { @@ -31,4 +43,33 @@ public List> procedures() { public Class benchmarkClass() { return NoOpBenchmark.class; } + + @Test + public void testNoSessionSetupFile() throws Exception { + // Check that there is no session setup file assigned to the worker's config + assertNull("Session setup file should be null", this.workConf.getSessionSetupFile()); + + List> workers = this.benchmark.makeWorkers(); + Worker worker = workers.get(0); + assertNull( + "Session setup file should be null", + worker.getWorkloadConfiguration().getSessionSetupFile()); + + // Make sure there are no rows in the table + this.testExecuteWork(); + + Table catalog_tbl = this.catalog.getTable("FAKE2"); + String sql = SQLUtil.getCountSQL(this.workConf.getDatabaseType(), catalog_tbl); + try (Statement stmt = conn.createStatement(); + ResultSet result = stmt.executeQuery(sql); ) { + + assertNotNull(result); + + boolean adv = result.next(); + assertTrue(sql, adv); + + int count = result.getInt(1); + assertEquals(0, count); + } + } } diff --git a/src/test/java/com/oltpbenchmark/benchmarks/noop/TestNoOpWorkerWithSessionSetupFile.java b/src/test/java/com/oltpbenchmark/benchmarks/noop/TestNoOpWorkerWithSessionSetupFile.java new file mode 100644 index 000000000..8ddd71f9a --- /dev/null +++ b/src/test/java/com/oltpbenchmark/benchmarks/noop/TestNoOpWorkerWithSessionSetupFile.java @@ -0,0 +1,82 @@ +/* + * Copyright 2016 by OLTPBenchmark Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oltpbenchmark.benchmarks.noop; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.oltpbenchmark.api.AbstractTestWorker; +import com.oltpbenchmark.api.BenchmarkModule; +import com.oltpbenchmark.api.Procedure; +import com.oltpbenchmark.api.Worker; +import com.oltpbenchmark.catalog.Table; +import com.oltpbenchmark.util.SQLUtil; +import java.nio.file.Paths; +import java.sql.ResultSet; +import java.sql.Statement; +import java.util.List; +import org.junit.Test; + +public class TestNoOpWorkerWithSessionSetupFile extends AbstractTestWorker { + + public TestNoOpWorkerWithSessionSetupFile() { + super( + null, + Paths.get("src", "test", "resources", "benchmarks", "noop", "sessionSetupFile-hsqldb.sql") + .toAbsolutePath() + .toString()); + } + + @Override + public List> procedures() { + return TestNoOpBenchmark.PROCEDURE_CLASSES; + } + + @Override + public Class benchmarkClass() { + return NoOpBenchmark.class; + } + + @Test + public void testSessionSetupFile() throws Exception { + // Check that there is no session setup file assigned to the worker's config + assertNotNull("Session setup file should not be null", this.workConf.getSessionSetupFile()); + + List> workers = this.benchmark.makeWorkers(); + Worker worker = workers.get(0); + assertNotNull( + "Session setup file should not be null", + worker.getWorkloadConfiguration().getSessionSetupFile()); + + // Make sure there are no rows in the table + this.testExecuteWork(); + + Table catalog_tbl = this.catalog.getTable("FAKE2"); + String sql = SQLUtil.getCountSQL(this.workConf.getDatabaseType(), catalog_tbl); + try (Statement stmt = conn.createStatement(); + ResultSet result = stmt.executeQuery(sql); ) { + + assertNotNull(result); + + boolean adv = result.next(); + assertTrue(sql, adv); + + int count = result.getInt(1); + assertTrue("FAKE2 table should have more 0 rows.", count > 0); + } + } +} diff --git a/src/test/resources/benchmarks/noop/sessionSetupFile-hsqldb.sql b/src/test/resources/benchmarks/noop/sessionSetupFile-hsqldb.sql new file mode 100644 index 000000000..78a516e89 --- /dev/null +++ b/src/test/resources/benchmarks/noop/sessionSetupFile-hsqldb.sql @@ -0,0 +1,3 @@ +-- Dummy session setup file for HSQLDB +INSERT INTO FAKE2 (ID) VALUES (1); +COMMIT; \ No newline at end of file