Repository: squashql/squashql
Pull request #317 (2024-04-24 09:56:37)

Simplify data loader API used for the tests


Patch:
diff --git a/bigquery/src/main/java/io/squashql/transaction/BigQueryDataLoader.java b/bigquery/src/main/java/io/squashql/transaction/BigQueryDataLoader.java
index 7720299..030ed8b 100644
--- a/bigquery/src/main/java/io/squashql/transaction/BigQueryDataLoader.java
+++ b/bigquery/src/main/java/io/squashql/transaction/BigQueryDataLoader.java
@@ -6,7 +6,6 @@ import io.squashql.BigQueryUtil;
 import io.squashql.list.Lists;
 import io.squashql.type.TableTypedField;
 import lombok.extern.slf4j.Slf4j;
-import org.eclipse.collections.impl.list.immutable.ImmutableListFactoryImpl;
 
 import java.time.LocalDate;
 import java.time.LocalDateTime;
@@ -34,14 +33,9 @@ public class BigQueryDataLoader implements DataLoader {
   }
 
   public void dropAndCreateInMemoryTable(String tableName, List<TableTypedField> fields) {
-    List<TableTypedField> list = ImmutableListFactoryImpl.INSTANCE
-            .ofAll(fields)
-            .newWith(new TableTypedField(tableName, SCENARIO_FIELD_NAME, String.class))
-            .castToList();
-
     TableId tableId = TableId.of(this.datasetName, tableName);
 
-    List<com.google.cloud.bigquery.Field> fieldList = list.stream()
+    List<com.google.cloud.bigquery.Field> fieldList = fields.stream()
             .map(f -> {
               if (f.type().equals(Lists.LongList.class)) {
                 return Field.of(f.name(), StandardSQLTypeName.INT64).toBuilder().setMode(Field.Mode.REPEATED).build();
@@ -70,25 +64,18 @@ public class BigQueryDataLoader implements DataLoader {
   }
 
   @Override
-  public void load(String scenario, String store, List<Object[]> tuples) {
-    // Check the table contains a column scenario.
-    ensureScenarioColumnIsPresent(store);
-
+  public void load(String store, List<Object[]> tuples) {
     List<TableTypedField> fields = BigQueryServiceAccountDatastore.getFieldsOrNull(this.bigquery, this.datasetName, store);
     List<InsertAllRequest.RowToInsert> list = new ArrayList<>();
     for (Object[] tuple : tuples) {
       Map<String, Object> m = new HashMap<>();
       for (int i = 0; i < fields.size(); i++) {
         String name = fields.get(i).name();
-        if (!name.equals(SCENARIO_FIELD_NAME)) {
-          Object o = tuple[i];
-          if (o != null && (o.getClass().equals(LocalDate.class) || o.getClass().equals(LocalDateTime.class))) {
-            o = o.toString();
-          }
-          m.put(name, o);
-        } else {
-          m.put(name, scenario);
+        Object o = tuple[i];
+        if (o != null && (o.getClass().equals(LocalDate.class) || o.getClass().equals(LocalDateTime.class))) {
+          o = o.toString();
         }
+        m.put(name, o);
       }
       list.add(InsertAllRequest.RowToInsert.of(m));
     }
@@ -128,7 +115,7 @@ public class BigQueryDataLoader implements DataLoader {
         if (attempt < MAX_SLEEPS) {
           sleepTime <<= 1;
           attempt++;
-          log.info("table.insert, retry " + attempt);
+          log.info("table.insert, retry {}", attempt);
         } else {
           log.info("table.insert after " + MAX_SLEEPS + " attempts. Abort.");
           throw exception;
@@ -137,16 +124,8 @@ public class BigQueryDataLoader implements DataLoader {
     }
   }
 
-  private void ensureScenarioColumnIsPresent(String store) {
-    List<TableTypedField> fields = BigQueryServiceAccountDatastore.getFieldsOrNull(this.bigquery, this.datasetName, store);
-    boolean found = fields.stream().anyMatch(f -> f.name().equals(SCENARIO_FIELD_NAME));
-    if (!found) {
-      throw new RuntimeException(String.format("%s field not found", SCENARIO_FIELD_NAME));
-    }
-  }
-
   @Override
-  public void loadCsv(String scenario, String table, String path, String delimiter, boolean header) {
+  public void loadCsv(String table, String path, String delimiter, boolean header) {
     throw new RuntimeException("not impl. yet");
   }
 }
diff --git a/clickhouse/pom.xml b/clickhouse/pom.xml
index e987e08..cb08a5a 100644
--- a/clickhouse/pom.xml
+++ b/clickhouse/pom.xml
@@ -40,12 +40,6 @@
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>io.squashql</groupId>
-      <artifactId>squashql-spark</artifactId>
-      <version>${project.version}</version>
-      <scope>test</scope>
-    </dependency>
     <dependency>
       <groupId>org.junit.jupiter</groupId>
       <artifactId>junit-jupiter</artifactId>
diff --git a/clickhouse/src/main/java/io/squashql/transaction/ClickHouseDataLoader.java b/clickhouse/src/main/java/io/squashql/transaction/ClickHouseDataLoader.java
index 883334b..ac470c0 100644
--- a/clickhouse/src/main/java/io/squashql/transaction/ClickHouseDataLoader.java
+++ b/clickhouse/src/main/java/io/squashql/transaction/ClickHouseDataLoader.java
@@ -3,10 +3,8 @@ package io.squashql.transaction;
 import com.clickhouse.jdbc.ClickHouseConnection;
 import com.clickhouse.jdbc.ClickHouseDataSource;
 import com.clickhouse.jdbc.ClickHouseStatement;
-import io.squashql.ClickHouseDatastore;
 import io.squashql.query.database.SqlUtils;
 import io.squashql.type.TableTypedField;
-import org.eclipse.collections.impl.list.immutable.ImmutableListFactoryImpl;
 
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
@@ -26,25 +24,17 @@ public class ClickHouseDataLoader implements DataLoader {
   }
 
   public void dropAndCreateInMemoryTable(String table, List<TableTypedField> fields) {
-    dropAndCreateInMemoryTable(this.clickHouseDataSource, table, fields, true);
+    dropAndCreateInMemoryTable(this.clickHouseDataSource, table, fields);
   }
 
   public static void dropAndCreateInMemoryTable(ClickHouseDataSource clickHouseDataSource,
                                                 String table,
-                                                List<TableTypedField> fields,
-                                                boolean cjMode) {
-    List<TableTypedField> list = cjMode ? ImmutableListFactoryImpl.INSTANCE
-            .ofAll(fields)
-            .newWith(new TableTypedField(table, SCENARIO_FIELD_NAME, String.class))
-            .castToList() : fields;
-
+                                                List<TableTypedField> fields) {
     try (ClickHouseConnection conn = clickHouseDataSource.getConnection();
          ClickHouseStatement stmt = conn.createStatement()) {
       stmt.execute("drop table if exists " + table);
-      int size = list.size();
       StringJoiner joiner = new StringJoiner(",", "(", ")");
-      for (int i = 0; i < size; i++) {
-        TableTypedField field = list.get(i);
+      for (TableTypedField field : fields) {
         String format = !List.class.isAssignableFrom(field.type()) ? "Nullable(%s)" : "%s";
         joiner.add(SqlUtils.backtickEscape(field.name()) + " " + String.format(format, classToClickHouseType(field.type())));
       }
@@ -55,9 +45,7 @@ public class ClickHouseDataLoader implements DataLoader {
   }
 
   @Override
-  public void load(String scenario, String table, List<Object[]> tuples) {
-    // Check the table contains a column scenario.
-    ensureScenarioColumnIsPresent(table);
+  public void load(String table, List<Object[]> tuples) {
     String join = String.join(",", IntStream.range(0, tuples.get(0).length + 1).mapToObj(i -> "?").toList());
     String pattern = "insert into " + table + " values(" + join + ")";
     try (ClickHouseConnection conn = this.clickHouseDataSource.getConnection();
@@ -67,7 +55,6 @@ public class ClickHouseDataLoader implements DataLoader {
         for (int i = 0; i < tuple.length; i++) {
           stmt.setObject(i + 1, tuple[i]);
         }
-        stmt.setObject(tuple.length + 1, scenario);
         stmt.addBatch();
       }
       stmt.executeBatch();
@@ -76,16 +63,8 @@ public class ClickHouseDataLoader implements DataLoader {
     }
   }
 
-  private void ensureScenarioColumnIsPresent(String store) {
-    List<TableTypedField> fields = ClickHouseDatastore.getFields(this.clickHouseDataSource, store);
-    boolean found = fields.stream().anyMatch(f -> f.name().equals(SCENARIO_FIELD_NAME));
-    if (!found) {
-      throw new RuntimeException(String.format("%s field not found", SCENARIO_FIELD_NAME));
-    }
-  }
-
   @Override
-  public void loadCsv(String scenario, String table, String path, String delimiter, boolean header) {
+  public void loadCsv(String table, String path, String delimiter, boolean header) {
     throw new RuntimeException("not implemented");
   }
 
diff --git a/core/src/main/java/io/squashql/query/AggregatedMeasure.java b/core/src/main/java/io/squashql/query/AggregatedMeasure.java
index 493aaa3..d7fd760 100644
--- a/core/src/main/java/io/squashql/query/AggregatedMeasure.java
+++ b/core/src/main/java/io/squashql/query/AggregatedMeasure.java
@@ -46,6 +46,10 @@ public class AggregatedMeasure implements BasicMeasure {
     this(alias, field, aggregationFunction, null);
   }
 
+  public AggregatedMeasure(@NonNull String alias, @NonNull Field field, @NonNull String aggregationFunction) {
+    this(alias, field, aggregationFunction, null);
+  }
+
   @Override
   public String alias() {
     return this.alias;
diff --git a/core/src/main/java/io/squashql/transaction/DataLoader.java b/core/src/main/java/io/squashql/transaction/DataLoader.java
index 5ee4d32..d88f3f4 100644
--- a/core/src/main/java/io/squashql/transaction/DataLoader.java
+++ b/core/src/main/java/io/squashql/transaction/DataLoader.java
@@ -8,11 +8,7 @@ public interface DataLoader {
 
   String SCENARIO_FIELD_NAME = "scenario";
 
-  void load(String scenario, String table, List<Object[]> tuples);
+  void load(String table, List<Object[]> tuples);
 
-  default void load(String table, List<Object[]> tuples) {
-    load(MAIN_SCENARIO_NAME, table, tuples);
-  }
-
-  void loadCsv(String scenario, String table, String path, String delimiter, boolean header);
+  void loadCsv(String table, String path, String delimiter, boolean header);
 }
diff --git a/duckdb/src/main/java/io/squashql/transaction/DuckDBDataLoader.java b/duckdb/src/main/java/io/squashql/transaction/DuckDBDataLoader.java
index 9143aaa..0aaa5b2 100644
--- a/duckdb/src/main/java/io/squashql/transaction/DuckDBDataLoader.java
+++ b/duckdb/src/main/java/io/squashql/transaction/DuckDBDataLoader.java
@@ -5,16 +5,15 @@ import io.squashql.jdbc.JdbcUtil;
 import io.squashql.query.database.SqlUtils;
 import io.squashql.table.Table;
 import io.squashql.type.TableTypedField;
-import org.eclipse.collections.impl.list.immutable.ImmutableListFactoryImpl;
 
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
-import java.util.Arrays;
-import java.util.Iterator;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.StringJoiner;
 
 public class DuckDBDataLoader implements DataLoader {
 
@@ -26,107 +25,60 @@ public class DuckDBDataLoader implements DataLoader {
 
   public void createOrReplaceTable(String tableName, Table table) {
     List<TableTypedField> fields = table.headers().stream().map(h -> new TableTypedField(tableName, h.name(), h.type())).toList();
-    createOrReplaceTable(this.datastore, tableName, fields, false);
-    loadWithOrWithoutScenario(null, tableName, table.iterator());
+    createOrReplaceTable(this.datastore, tableName, fields);
+    List<Object[]> tuples = new ArrayList<>();
+    for (List<Object> row : table) {
+      tuples.add(row.toArray());
+    }
+    load(tableName, tuples);
   }
 
   public void createOrReplaceTable(String tableName, List<TableTypedField> fields) {
-    createOrReplaceTable(tableName, fields, true);
-  }
-
-  public void createOrReplaceTable(String tableName, List<TableTypedField> fields, boolean cjMode) {
-    createOrReplaceTable(this.datastore, tableName, fields, cjMode);
+    createOrReplaceTable(this.datastore, tableName, fields);
   }
 
-  public static void createOrReplaceTable(DuckDBDatastore datastore, String tableName, List<TableTypedField> fields,
-                                          boolean cjMode) {
-    List<TableTypedField> list = cjMode ? ImmutableListFactoryImpl.INSTANCE
-            .ofAll(fields)
-            .newWith(new TableTypedField(tableName, SCENARIO_FIELD_NAME, String.class))
-            .castToList() : fields;
-
+  public static void createOrReplaceTable(DuckDBDatastore datastore, String tableName, List<TableTypedField> fields) {
     try (Connection conn = datastore.getConnection();
          Statement stmt = conn.createStatement()) {
-      StringBuilder sb = new StringBuilder();
-      sb.append("(");
-      int size = list.size();
-      for (int i = 0; i < size; i++) {
-        TableTypedField field = list.get(i);
-        sb.append("\"").append(field.name()).append("\" ").append(JdbcUtil.classToSqlType(field.type()));
-        if (i < size - 1) {
-          sb.append(", ");
-        }
+      StringJoiner sb = new StringJoiner(", ", "(", ")");
+      for (TableTypedField field : fields) {
+        sb.add("\"" + field.name() + "\" " + JdbcUtil.classToSqlType(field.type()));
       }
-      sb.append(")");
-      stmt.execute("create or replace table \"" + tableName + "\"" + sb + ";"); // REMOVE or replace
+      stmt.execute("create or replace table \"" + tableName + "\"" + sb + ";");
     } catch (SQLException e) {
       throw new RuntimeException(e);
     }
   }
 
   @Override
-  public void load(String scenario, String table, List<Object[]> tuples) {
-    loadWithOrWithoutScenario(scenario, table, tuples.stream().map(t -> Arrays.asList(t)).toList().iterator());
-  }
-
-  private void loadWithOrWithoutScenario(String scenario, String table, Iterator<List<Object>> tuplesIterator) {
-    // Check the table contains a column scenario.
-    if (scenario != null && !scenario.equals(MAIN_SCENARIO_NAME)) {
-      ensureScenarioColumnIsPresent(table);
-    }
-
-    boolean addScenario = scenarioColumnIsPresent(table);
-    String sql = "insert into \"" + table + "\" values ";
+  public void load(String table, List<Object[]> tuples) {
+    StringJoiner sql = new StringJoiner(",", "insert into \"" + table + "\" values ", "");
     try (Connection conn = this.datastore.getConnection();
          Statement stmt = conn.createStatement()) {
-      while (tuplesIterator.hasNext()) {
-        List<Object> tuple = tuplesIterator.next();
-        StringBuilder sb = new StringBuilder();
-        sb.append('(');
-        for (int i = 0; i < tuple.size(); i++) {
-          Object o = tuple.get(i);
+      for (Object[] tuple : tuples) {
+        StringJoiner sb = new StringJoiner(",", "(", ")");
+        for (Object o : tuple) {
           if (o != null && (o.getClass().equals(LocalDate.class) || o.getClass().equals(LocalDateTime.class))) {
             o = o.toString();
           }
 
           if (o instanceof String) {
-            sb.append('\'').append(SqlUtils.escapeSingleQuote((String) o, "''")).append('\'');
+            sb.add('\'' + SqlUtils.escapeSingleQuote((String) o, "''") + '\'');
           } else {
-            sb.append(o);
+            sb.add(String.valueOf(o));
           }
-          sb.append(",");
-        }
-
-        if (addScenario) {
-          sb.append('\'').append(scenario).append('\'').append("),");
-          sql += sb.toString();
-        } else {
-          String s = sb.toString();
-          sql += s.substring(0, s.length() - 1) + "),";
         }
+        sql.add(sb.toString());
       }
       // addBatch is Not supported.
-      stmt.execute(sql.substring(0, sql.length() - 1));
+      stmt.execute(sql.toString());
     } catch (SQLException e) {
       throw new RuntimeException(e);
     }
   }
 
-  private void ensureScenarioColumnIsPresent(String store) {
-    List<TableTypedField> fields = this.datastore.storeByName().get(store).fields();
-    boolean found = fields.stream().anyMatch(f -> f.name().equals(SCENARIO_FIELD_NAME));
-    if (!found) {
-      throw new RuntimeException(String.format("%s field not found", SCENARIO_FIELD_NAME));
-    }
-  }
-
-  private boolean scenarioColumnIsPresent(String store) {
-    List<TableTypedField> fields = this.datastore.storeByName().get(store).fields();
-    return fields.stream().anyMatch(f -> f.name().equals(SCENARIO_FIELD_NAME));
-  }
-
   @Override
-  public void loadCsv(String scenario, String table, String path, String delimiter, boolean header) {
+  public void loadCsv(String table, String path, String delimiter, boolean header) {
     throw new RuntimeException("Not implemented");
   }
 }
diff --git a/snowflake/src/main/java/io/squashql/transaction/SnowflakeDataLoader.java b/snowflake/src/main/java/io/squashql/transaction/SnowflakeDataLoader.java
index e9a8cc8..6f516db 100644
--- a/snowflake/src/main/java/io/squashql/transaction/SnowflakeDataLoader.java
+++ b/snowflake/src/main/java/io/squashql/transaction/SnowflakeDataLoader.java
@@ -3,7 +3,6 @@ package io.squashql.transaction;
 import io.squashql.SnowflakeDatastore;
 import io.squashql.jdbc.JdbcUtil;
 import io.squashql.type.TableTypedField;
-import org.eclipse.collections.impl.list.immutable.ImmutableListFactoryImpl;
 
 import java.sql.Connection;
 import java.sql.PreparedStatement;
@@ -12,6 +11,7 @@ import java.sql.Statement;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.List;
+import java.util.StringJoiner;
 import java.util.stream.IntStream;
 
 public class SnowflakeDataLoader implements DataLoader {
@@ -23,7 +23,7 @@ public class SnowflakeDataLoader implements DataLoader {
   }
 
   public void dropTable(String table) {
-    try (Statement statement = snowflakeDatastore.getConnection().createStatement()) {
+    try (Statement statement = this.snowflakeDatastore.getConnection().createStatement()) {
       statement.execute("drop table \"" + table + "\";");
     } catch (SQLException e) {
       throw new RuntimeException(e);
@@ -31,29 +31,16 @@ public class SnowflakeDataLoader implements DataLoader {
   }
 
   public void createOrReplaceTable(String table, List<TableTypedField> fields) {
-    createOrReplaceTable(this.snowflakeDatastore, table, fields, true);
+    createOrReplaceTable(this.snowflakeDatastore, table, fields);
   }
 
-  public static void createOrReplaceTable(SnowflakeDatastore snowflakeDatastore, String table, List<TableTypedField> fields,
-                                          boolean cjMode) {
-    List<TableTypedField> list = cjMode ? ImmutableListFactoryImpl.INSTANCE
-            .ofAll(fields)
-            .newWith(new TableTypedField(table, SCENARIO_FIELD_NAME, String.class))
-            .castToList() : fields;
-
+  public static void createOrReplaceTable(SnowflakeDatastore snowflakeDatastore, String table, List<TableTypedField> fields) {
     try (Connection conn = snowflakeDatastore.getConnection();
          Statement stmt = conn.createStatement()) {
-      StringBuilder sb = new StringBuilder();
-      sb.append("(");
-      int size = list.size();
-      for (int i = 0; i < size; i++) {
-        TableTypedField field = list.get(i);
-        sb.append("\"").append(field.name()).append("\" ").append(JdbcUtil.classToSqlType(field.type()));
-        if (i < size - 1) {
-          sb.append(", ");
-        }
+      StringJoiner sb = new StringJoiner(", ", "(", ")");
+      for (TableTypedField field : fields) {
+        sb.add("\"" + field.name() + "\" " + JdbcUtil.classToSqlType(field.type()));
       }
-      sb.append(")");
       stmt.execute("create or replace table \"" + table + "\"" + sb + ";");
     } catch (SQLException e) {
       throw new RuntimeException(e);
@@ -61,10 +48,8 @@ public class SnowflakeDataLoader implements DataLoader {
   }
 
   @Override
-  public void load(String scenario, String table, List<Object[]> tuples) {
-    // Check the table contains a column scenario.
-    ensureScenarioColumnIsPresent(table);
-    String join = String.join(",", IntStream.range(0, tuples.get(0).length + 1).mapToObj(i -> "?").toList());
+  public void load(String table, List<Object[]> tuples) {
+    String join = String.join(",", IntStream.range(0, tuples.get(0).length).mapToObj(i -> "?").toList());
     String pattern = "insert into \"" + table + "\" values(" + join + ")";
     try (Connection conn = this.snowflakeDatastore.getConnection();
          PreparedStatement stmt = conn.prepareStatement(pattern)) {
@@ -76,7 +61,6 @@ public class SnowflakeDataLoader implements DataLoader {
           }
           stmt.setObject(i + 1, o);
         }
-        stmt.setObject(tuple.length + 1, scenario);
         stmt.addBatch();
       }
       stmt.executeBatch();
@@ -85,16 +69,8 @@ public class SnowflakeDataLoader implements DataLoader {
     }
   }
 
-  private void ensureScenarioColumnIsPresent(String store) {
-    List<TableTypedField> fields = this.snowflakeDatastore.storeByName().get(store).fields();
-    boolean found = fields.stream().anyMatch(f -> f.name().equals(SCENARIO_FIELD_NAME));
-    if (!found) {
-      throw new RuntimeException(String.format("%s field not found", SCENARIO_FIELD_NAME));
-    }
-  }
-
   @Override
-  public void loadCsv(String scenario, String table, String path, String delimiter, boolean header) {
-    // Not implemented
+  public void loadCsv(String table, String path, String delimiter, boolean header) {
+    throw new RuntimeException("not implemented");
   }
 }
diff --git a/spark/src/main/java/io/squashql/transaction/SparkDataLoader.java b/spark/src/main/java/io/squashql/transaction/SparkDataLoader.java
index 5dd084e..0616392 100644
--- a/spark/src/main/java/io/squashql/transaction/SparkDataLoader.java
+++ b/spark/src/main/java/io/squashql/transaction/SparkDataLoader.java
@@ -6,10 +6,7 @@ import io.squashql.type.TableTypedField;
 import org.apache.spark.sql.*;
 import org.apache.spark.sql.catalog.Table;
 import org.apache.spark.sql.types.StructType;
-import org.eclipse.collections.api.list.ImmutableList;
-import org.eclipse.collections.impl.list.immutable.ImmutableListFactoryImpl;
 
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
@@ -22,19 +19,12 @@ public class SparkDataLoader implements DataLoader {
   }
 
   public void createTemporaryTable(String table, List<TableTypedField> fields) {
-    createTemporaryTable(this.spark, table, fields, true);
+    createTemporaryTable(this.spark, table, fields);
   }
 
-  public void createTemporaryTable(String table, List<TableTypedField> fields, boolean cjMode) {
-    createTemporaryTable(this.spark, table, fields, cjMode);
-  }
 
-  public static void createTemporaryTable(SparkSession spark, String table, List<TableTypedField> fields, boolean cjMode) {
-    ImmutableList<TableTypedField> all = ImmutableListFactoryImpl.INSTANCE.ofAll(fields);
-    if (cjMode) {
-      all = all.newWith(new TableTypedField(table, SCENARIO_FIELD_NAME, String.class));
-    }
-    StructType schema = SparkUtil.createSchema(all.castToList());
+  public static void createTemporaryTable(SparkSession spark, String table, List<TableTypedField> fields) {
+    StructType schema = SparkUtil.createSchema(fields);
     spark.conf().set("spark.sql.caseSensitive", String.valueOf(true)); // without it, table names are lowercase.
     spark
             .createDataFrame(Collections.emptyList(), schema)
@@ -42,24 +32,9 @@ public class SparkDataLoader implements DataLoader {
   }
 
   @Override
-  public void load(String scenario, String table, List<Object[]> tuples) {
-    // Check the table contains a column scenario.
-    if (!scenario.equals(DataLoader.MAIN_SCENARIO_NAME)) {
-      ensureScenarioColumnIsPresent(table);
-    }
-
-    boolean addScenario = scenarioColumnIsPresent(table);
-    List<Row> rows = tuples.stream().map(tuple -> {
-      Object[] copy = tuple;
-      if (addScenario) {
-        copy = Arrays.copyOf(tuple, tuple.length + 1);
-        copy[copy.length - 1] = scenario;
-      }
-      return RowFactory.create(copy);
-    }).toList();
-
+  public void load(String table, List<Object[]> tuples) {
     Dataset<Row> dataFrame = this.spark.createDataFrame(
-            rows,
+            tuples.stream().map(RowFactory::create).toList(),
             SparkUtil.createSchema(SparkDatastore.getFields(this.spark, table)));// to load pojo
     appendDataset(this.spark, table, dataFrame);
   }
@@ -73,24 +48,12 @@ public class SparkDataLoader implements DataLoader {
     spark.catalog().dropTempView(viewName);
   }
 
-  private void ensureScenarioColumnIsPresent(String store) {
-    if (!scenarioColumnIsPresent(store)) {
-      throw new RuntimeException(String.format("%s field not found", SCENARIO_FIELD_NAME));
-    }
-  }
-
-  private boolean scenarioColumnIsPresent(String store) {
-    List<TableTypedField> fields = SparkDatastore.getFields(this.spark, store);
-    return fields.stream().anyMatch(f -> f.name().equals(SCENARIO_FIELD_NAME));
-  }
-
   @Override
-  public void loadCsv(String scenario, String store, String path, String delimiter, boolean header) {
+  public void loadCsv(String store, String path, String delimiter, boolean header) {
     Dataset<Row> dataFrame = this.spark.read()
             .option("delimiter", delimiter)
             .option("header", true)
-            .csv(path)
-            .withColumn(SCENARIO_FIELD_NAME, functions.lit(scenario));
+            .csv(path);
 
     Table table = null;
     try {


Test patch:
diff --git a/core/src/test/java/io/squashql/query/ATestBinaryOperationMeasure.java b/core/src/test/java/io/squashql/query/ATestBinaryOperationMeasure.java
index 2850590..d6d10af 100644
--- a/core/src/test/java/io/squashql/query/ATestBinaryOperationMeasure.java
+++ b/core/src/test/java/io/squashql/query/ATestBinaryOperationMeasure.java
@@ -13,8 +13,6 @@ import org.junit.jupiter.api.TestInstance;
 import java.util.List;
 import java.util.Map;
 
-import static io.squashql.transaction.DataLoader.MAIN_SCENARIO_NAME;
-
 @TestClass
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 public abstract class ATestBinaryOperationMeasure extends ABaseTestQuery {
@@ -32,7 +30,7 @@ public abstract class ATestBinaryOperationMeasure extends ABaseTestQuery {
 
   @Override
   protected void loadData() {
-    this.tm.load(MAIN_SCENARIO_NAME, this.storeName, List.of(
+    this.tm.load(this.storeName, List.of(
             new Object[]{"bottle", "drink", 20d, 10l},
             new Object[]{"cookie", "food", 30d, 10l}
     ));
diff --git a/core/src/test/java/io/squashql/query/ATestDocDrillacross.java b/core/src/test/java/io/squashql/query/ATestDocDrillacross.java
index 84f1e69..6a113bb 100644
--- a/core/src/test/java/io/squashql/query/ATestDocDrillacross.java
+++ b/core/src/test/java/io/squashql/query/ATestDocDrillacross.java
@@ -16,7 +16,6 @@ import java.util.Map;
 import static io.squashql.query.Functions.sum;
 import static io.squashql.query.TableField.tableField;
 import static io.squashql.query.TableField.tableFields;
-import static io.squashql.transaction.DataLoader.MAIN_SCENARIO_NAME;
 
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 @TestClass(ignore = {TestClass.Type.SPARK, TestClass.Type.BIGQUERY, TestClass.Type.SNOWFLAKE, TestClass.Type.CLICKHOUSE})
@@ -36,13 +35,13 @@ public abstract class ATestDocDrillacross extends ABaseTestQuery {
 
   @Override
   protected void loadData() {
-    this.tm.load(MAIN_SCENARIO_NAME, "shipment", List.of(
+    this.tm.load("shipment", List.of(
             new Object[]{"A", 15},
             new Object[]{"B", 23},
             new Object[]{"C", 16}
     ));
 
-    this.tm.load(MAIN_SCENARIO_NAME, "return", List.of(
+    this.tm.load("return", List.of(
             new Object[]{"A", 1, "defective"},
             new Object[]{"C", 3, "unwanted"},
             new Object[]{"D", 1, "unwanted"}
diff --git a/core/src/test/java/io/squashql/query/ATestDocGroupComparison.java b/core/src/test/java/io/squashql/query/ATestDocGroupComparison.java
index 541405a..23bf4e2 100644
--- a/core/src/test/java/io/squashql/query/ATestDocGroupComparison.java
+++ b/core/src/test/java/io/squashql/query/ATestDocGroupComparison.java
@@ -28,18 +28,19 @@ public abstract class ATestDocGroupComparison extends ABaseTestQuery {
 
   @Override
   protected Map<String, List<TableTypedField>> getFieldsByStore() {
+    TableTypedField scenario = new TableTypedField("store", "scenario", String.class);
     TableTypedField salePrice = new TableTypedField("store", "saleprice", double.class);
     TableTypedField loavesSold = new TableTypedField("store", "loavessold", int.class);
     TableTypedField pos = new TableTypedField("store", "pointofsale", String.class);
-    return Map.of("store", List.of(salePrice, loavesSold, pos));
+    return Map.of("store", List.of(scenario, salePrice, loavesSold, pos));
   }
 
   @Override
   protected void loadData() {
-    this.tm.load(MAIN_SCENARIO_NAME, "store", List.of(new Object[]{2d, 100, "A"}, new Object[]{2d, 80, "B"}));
-    this.tm.load("s1", "store", List.of(new Object[]{3d, 74, "A"}, new Object[]{3d, 50, "B"}));
-    this.tm.load("s2", "store", List.of(new Object[]{4d, 55, "A"}, new Object[]{4d, 20, "B"}));
-    this.tm.load("s3", "store", List.of(new Object[]{2d, 100, "A"}, new Object[]{3d, 50, "B"}));
+    this.tm.load("store", List.of(new Object[]{MAIN_SCENARIO_NAME, 2d, 100, "A"}, new Object[]{MAIN_SCENARIO_NAME, 2d, 80, "B"}));
+    this.tm.load("store", List.of(new Object[]{"s1", 3d, 74, "A"}, new Object[]{"s1", 3d, 50, "B"}));
+    this.tm.load("store", List.of(new Object[]{"s2", 4d, 55, "A"}, new Object[]{"s2", 4d, 20, "B"}));
+    this.tm.load("store", List.of(new Object[]{"s3", 2d, 100, "A"}, new Object[]{"s3", 3d, 50, "B"}));
   }
 
   @Test
diff --git a/core/src/test/java/io/squashql/query/ATestDocPeriodComparison.java b/core/src/test/java/io/squashql/query/ATestDocPeriodComparison.java
index 15dd13a..0a17e1a 100644
--- a/core/src/test/java/io/squashql/query/ATestDocPeriodComparison.java
+++ b/core/src/test/java/io/squashql/query/ATestDocPeriodComparison.java
@@ -15,7 +15,6 @@ import java.util.Map;
 
 import static io.squashql.query.TableField.tableField;
 import static io.squashql.query.TableField.tableFields;
-import static io.squashql.transaction.DataLoader.MAIN_SCENARIO_NAME;
 
 /**
  * This test class is used to verify and print tables for the documentation. Nothing is asserted in those tests this is
@@ -37,7 +36,7 @@ public abstract class ATestDocPeriodComparison extends ABaseTestQuery {
 
   @Override
   protected void loadData() {
-    this.tm.load(MAIN_SCENARIO_NAME, "student", List.of(
+    this.tm.load("student", List.of(
             // 2022 - s1
             new Object[]{"Paul", "mathematics", 75, 2022, 1},
             new Object[]{"Paul", "english", 73, 2022, 1},
diff --git a/core/src/test/java/io/squashql/query/ATestGrandTotalAlongAncestorsComparison.java b/core/src/test/java/io/squashql/query/ATestGrandTotalAlongAncestorsComparison.java
index dfc5a5b..4bf8397 100644
--- a/core/src/test/java/io/squashql/query/ATestGrandTotalAlongAncestorsComparison.java
+++ b/core/src/test/java/io/squashql/query/ATestGrandTotalAlongAncestorsComparison.java
@@ -17,7 +17,6 @@ import static io.squashql.query.TableField.tableField;
 import static io.squashql.query.TableField.tableFields;
 import static io.squashql.query.database.QueryEngine.GRAND_TOTAL;
 import static io.squashql.query.database.QueryEngine.TOTAL;
-import static io.squashql.transaction.DataLoader.MAIN_SCENARIO_NAME;
 
 @TestClass
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@@ -40,7 +39,7 @@ public abstract class ATestGrandTotalAlongAncestorsComparison extends ABaseTestQ
 
   @Override
   protected void loadData() {
-    this.tm.load(MAIN_SCENARIO_NAME, this.storeName, List.of(
+    this.tm.load(this.storeName, List.of(
             new Object[]{"paris", "france", "eu", "car", 1d},
             new Object[]{"paris", "france", "eu", "home", 2d},
             new Object[]{"paris", "france", "eu", "hobbies", 1d},
diff --git a/core/src/test/java/io/squashql/query/ATestGrandTotalComparison.java b/core/src/test/java/io/squashql/query/ATestGrandTotalComparison.java
index e0e7377..fa4ce93 100644
--- a/core/src/test/java/io/squashql/query/ATestGrandTotalComparison.java
+++ b/core/src/test/java/io/squashql/query/ATestGrandTotalComparison.java
@@ -17,7 +17,6 @@ import static io.squashql.query.TableField.tableField;
 import static io.squashql.query.TableField.tableFields;
 import static io.squashql.query.database.QueryEngine.GRAND_TOTAL;
 import static io.squashql.query.database.QueryEngine.TOTAL;
-import static io.squashql.transaction.DataLoader.MAIN_SCENARIO_NAME;
 
 @TestClass
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@@ -40,7 +39,7 @@ public abstract class ATestGrandTotalComparison extends ABaseTestQuery {
 
   @Override
   protected void loadData() {
-    this.tm.load(MAIN_SCENARIO_NAME, this.storeName, List.of(
+    this.tm.load(this.storeName, List.of(
             new Object[]{"paris", "france", "eu", "car", 1d},
             new Object[]{"paris", "france", "eu", "home", 2d},
             new Object[]{"paris", "france", "eu", "hobbies", 1d},
diff --git a/core/src/test/java/io/squashql/query/ATestGroupComparison.java b/core/src/test/java/io/squashql/query/ATestGroupComparison.java
index 0a16266..7f306df 100644
--- a/core/src/test/java/io/squashql/query/ATestGroupComparison.java
+++ b/core/src/test/java/io/squashql/query/ATestGroupComparison.java
@@ -41,31 +41,32 @@ public abstract class ATestGroupComparison extends ABaseTestQuery {
 
   @Override
   protected Map<String, List<TableTypedField>> getFieldsByStore() {
+    TableTypedField scenario = new TableTypedField(this.storeName, "scenario", String.class);
     TableTypedField ean = new TableTypedField(this.storeName, "ean", String.class);
     TableTypedField category = new TableTypedField(this.storeName, "category", String.class);
     TableTypedField price = new TableTypedField(this.storeName, "price", double.class);
     TableTypedField qty = new TableTypedField(this.storeName, "quantity", int.class);
-    return Map.of(this.storeName, List.of(ean, category, price, qty));
+    return Map.of(this.storeName, List.of(scenario, ean, category, price, qty));
   }
 
   @Override
   protected void loadData() {
-    this.tm.load(MAIN_SCENARIO_NAME, this.storeName, List.of(
-            new Object[]{"bottle", "drink", 2d, 11},
-            new Object[]{"cookie", "food", 3d, 20},
-            new Object[]{"shirt", "cloth", 10d, 3}
+    this.tm.load(this.storeName, List.of(
+            new Object[]{MAIN_SCENARIO_NAME, "bottle", "drink", 2d, 11},
+            new Object[]{MAIN_SCENARIO_NAME, "cookie", "food", 3d, 20},
+            new Object[]{MAIN_SCENARIO_NAME, "shirt", "cloth", 10d, 3}
     ));
 
-    this.tm.load("s1", this.storeName, List.of(
-            new Object[]{"bottle", "drink", 4d, 9},
-            new Object[]{"cookie", "food", 4d, 20},
-            new Object[]{"shirt", "cloth", 11d, 3}
+    this.tm.load(this.storeName, List.of(
+            new Object[]{"s1", "bottle", "drink", 4d, 9},
+            new Object[]{"s1", "cookie", "food", 4d, 20},
+            new Object[]{"s1", "shirt", "cloth", 11d, 3}
     ));
 
-    this.tm.load("s2", this.storeName, List.of(
-            new Object[]{"bottle", "drink", 1.5d, 12},
-            new Object[]{"cookie", "food", 2.5d, 20},
-            new Object[]{"shirt", "cloth", 9d, 3}
+    this.tm.load(this.storeName, List.of(
+            new Object[]{"s2", "bottle", "drink", 1.5d, 12},
+            new Object[]{"s2", "cookie", "food", 2.5d, 20},
+            new Object[]{"s2", "shirt", "cloth", 9d, 3}
     ));
   }
 
diff --git a/core/src/test/java/io/squashql/query/ATestParentComparison.java b/core/src/test/java/io/squashql/query/ATestParentComparison.java
index 5900bb2..4b743c3 100644
--- a/core/src/test/java/io/squashql/query/ATestParentComparison.java
+++ b/core/src/test/java/io/squashql/query/ATestParentComparison.java
@@ -18,7 +18,6 @@ import static io.squashql.query.Functions.*;
 import static io.squashql.query.TableField.tableFields;
 import static io.squashql.query.database.QueryEngine.GRAND_TOTAL;
 import static io.squashql.query.database.QueryEngine.TOTAL;
-import static io.squashql.transaction.DataLoader.MAIN_SCENARIO_NAME;
 
 @TestClass
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@@ -41,7 +40,7 @@ public abstract class ATestParentComparison extends ABaseTestQuery {
 
   @Override
   protected void loadData() {
-    this.tm.load(MAIN_SCENARIO_NAME, this.storeName, List.of(
+    this.tm.load(this.storeName, List.of(
             new Object[]{"paris", "france", "eu", 2d},
             new Object[]{"lyon", "france", "eu", 1d},
             new Object[]{"monaco", null, "eu", 1d}, // to have a null value as a parent
diff --git a/core/src/test/java/io/squashql/query/ATestParentComparisonWithOtherColumn.java b/core/src/test/java/io/squashql/query/ATestParentComparisonWithOtherColumn.java
index ac50f89..9dedb0b 100644
--- a/core/src/test/java/io/squashql/query/ATestParentComparisonWithOtherColumn.java
+++ b/core/src/test/java/io/squashql/query/ATestParentComparisonWithOtherColumn.java
@@ -14,7 +14,6 @@ import java.util.List;
 import java.util.Map;
 
 import static io.squashql.query.TableField.tableFields;
-import static io.squashql.transaction.DataLoader.MAIN_SCENARIO_NAME;
 
 @TestClass
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@@ -34,7 +33,7 @@ public abstract class ATestParentComparisonWithOtherColumn extends ABaseTestQuer
 
   @Override
   protected void loadData() {
-    this.tm.load(MAIN_SCENARIO_NAME, this.storeName, List.of(
+    this.tm.load(this.storeName, List.of(
             new Object[]{"paris", "france", "eu", "car", 1d},
             new Object[]{"paris", "france", "eu", "home", 2d},
             new Object[]{"paris", "france", "eu", "hobbies", 1d},
diff --git a/core/src/test/java/io/squashql/query/ATestPartialHierarchicalMeasureComparison.java b/core/src/test/java/io/squashql/query/ATestPartialHierarchicalMeasureComparison.java
index 91dc9d8..5b4a9d0 100644
--- a/core/src/test/java/io/squashql/query/ATestPartialHierarchicalMeasureComparison.java
+++ b/core/src/test/java/io/squashql/query/ATestPartialHierarchicalMeasureComparison.java
@@ -25,7 +25,6 @@ import static io.squashql.query.ComparisonMethod.DIVIDE;
 import static io.squashql.query.Functions.*;
 import static io.squashql.query.database.QueryEngine.GRAND_TOTAL;
 import static io.squashql.query.database.QueryEngine.TOTAL;
-import static io.squashql.transaction.DataLoader.MAIN_SCENARIO_NAME;
 
 @TestClass
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@@ -50,7 +49,7 @@ public abstract class ATestPartialHierarchicalMeasureComparison extends ABaseTes
 
   @Override
   protected void loadData() {
-    this.tm.load(MAIN_SCENARIO_NAME, this.storeName, List.of(
+    this.tm.load(this.storeName, List.of(
             new Object[]{"paris", "france", "eu", "car", 2d},
             new Object[]{"paris", "france", "eu", "home", 4d},
             new Object[]{"paris", "france", "eu", "hobbies", 1d},
diff --git a/core/src/test/java/io/squashql/query/ATestPeriodComparison.java b/core/src/test/java/io/squashql/query/ATestPeriodComparison.java
index 9e762f7..2d53d90 100644
--- a/core/src/test/java/io/squashql/query/ATestPeriodComparison.java
+++ b/core/src/test/java/io/squashql/query/ATestPeriodComparison.java
@@ -5,7 +5,6 @@ import io.squashql.query.builder.Query;
 import io.squashql.query.database.SqlUtils;
 import io.squashql.query.dto.Period;
 import io.squashql.table.Table;
-import io.squashql.transaction.DataLoader;
 import io.squashql.type.TableTypedField;
 import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.*;
@@ -20,11 +19,7 @@ import java.util.Map;
 import static io.squashql.query.ComparisonMethod.ABSOLUTE_DIFFERENCE;
 import static io.squashql.query.Functions.criterion;
 import static io.squashql.query.Functions.eq;
-import static io.squashql.query.TableField.tableField;
-import static io.squashql.query.TableField.tableFields;
 import static io.squashql.query.database.QueryEngine.GRAND_TOTAL;
-import static io.squashql.query.database.QueryEngine.TOTAL;
-import static io.squashql.transaction.DataLoader.SCENARIO_FIELD_NAME;
 
 @TestClass
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@@ -60,43 +55,43 @@ public abstract class ATestPeriodComparison extends ABaseTestQuery {
   protected void loadData() {
     this.tm.load(this.storeName, List.of(
             // 2022
-            new Object[]{"bottle", "drink", 20d, 10l, 2022l, 1, 1, 1, LocalDate.of(2022, 1, 1)},
-            new Object[]{"bottle", "drink", 10d, 5l, 2022l, 1, 2, 4, LocalDate.of(2022, 4, 1)},
-            new Object[]{"bottle", "drink", 20d, 10l, 2022l, 2, 3, 8, LocalDate.of(2022, 8, 1)},
-            new Object[]{"bottle", "drink", 10d, 5l, 2022l, 2, 4, 12, LocalDate.of(2022, 12, 1)},
+            new Object[]{"bottle", "drink", 20d, 10L, 2022L, 1, 1, 1, LocalDate.of(2022, 1, 1)},
+            new Object[]{"bottle", "drink", 10d, 5L, 2022L, 1, 2, 4, LocalDate.of(2022, 4, 1)},
+            new Object[]{"bottle", "drink", 20d, 10L, 2022L, 2, 3, 8, LocalDate.of(2022, 8, 1)},
+            new Object[]{"bottle", "drink", 10d, 5L, 2022L, 2, 4, 12, LocalDate.of(2022, 12, 1)},
 
-            new Object[]{"cookie", "food", 60d, 20l, 2022l, 1, 1, 2, LocalDate.of(2022, 2, 1)},
-            new Object[]{"cookie", "food", 30d, 10l, 2022l, 1, 2, 5, LocalDate.of(2022, 5, 1)},
-            new Object[]{"cookie", "food", 15d, 5l, 2022l, 2, 3, 9, LocalDate.of(2022, 9, 1)},
-            new Object[]{"cookie", "food", 15d, 5l, 2022l, 2, 4, 11, LocalDate.of(2022, 11, 1)},
+            new Object[]{"cookie", "food", 60d, 20L, 2022L, 1, 1, 2, LocalDate.of(2022, 2, 1)},
+            new Object[]{"cookie", "food", 30d, 10L, 2022L, 1, 2, 5, LocalDate.of(2022, 5, 1)},
+            new Object[]{"cookie", "food", 15d, 5L, 2022L, 2, 3, 9, LocalDate.of(2022, 9, 1)},
+            new Object[]{"cookie", "food", 15d, 5L, 2022L, 2, 4, 11, LocalDate.of(2022, 11, 1)},
 
-            new Object[]{"shirt", "cloth", 20d, 2l, 2022l, 1, 1, 3, LocalDate.of(2022, 3, 1)},
-            new Object[]{"shirt", "cloth", 40d, 4l, 2022l, 1, 2, 6, LocalDate.of(2022, 6, 1)},
-            new Object[]{"shirt", "cloth", 50d, 5l, 2022l, 2, 3, 7, LocalDate.of(2022, 7, 1)},
-            new Object[]{"shirt", "cloth", 10d, 1l, 2022l, 2, 4, 10, LocalDate.of(2022, 10, 1)},
+            new Object[]{"shirt", "cloth", 20d, 2L, 2022L, 1, 1, 3, LocalDate.of(2022, 3, 1)},
+            new Object[]{"shirt", "cloth", 40d, 4L, 2022L, 1, 2, 6, LocalDate.of(2022, 6, 1)},
+            new Object[]{"shirt", "cloth", 50d, 5L, 2022L, 2, 3, 7, LocalDate.of(2022, 7, 1)},
+            new Object[]{"shirt", "cloth", 10d, 1L, 2022L, 2, 4, 10, LocalDate.of(2022, 10, 1)},
 
             // 2023 (same data but 2023)
-            new Object[]{"bottle", "drink", 20d, 10l, 2023l, 1, 1, 1, LocalDate.of(2023, 1, 1)},
-            new Object[]{"bottle", "drink", 10d, 5l, 2023l, 1, 2, 4, LocalDate.of(2023, 4, 1)},
-            new Object[]{"bottle", "drink", 20d, 10l, 2023l, 2, 3, 8, LocalDate.of(2023, 8, 1)},
-            new Object[]{"bottle", "drink", 10d, 5l, 2023l, 2, 4, 12, LocalDate.of(2023, 12, 1)},
-
-            new Object[]{"cookie", "food", 60d, 20l, 2023l, 1, 1, 2, LocalDate.of(2023, 2, 1)},
-            new Object[]{"cookie", "food", 30d, 10l, 2023l, 1, 2, 5, LocalDate.of(2023, 5, 1)},
-            new Object[]{"cookie", "food", 15d, 5l, 2023l, 2, 3, 9, LocalDate.of(2023, 9, 1)},
-            new Object[]{"cookie", "food", 15d, 5l, 2023l, 2, 4, 11, LocalDate.of(2023, 11, 1)},
-
-            new Object[]{"shirt", "cloth", 20d, 2l, 2023l, 1, 1, 3, LocalDate.of(2023, 3, 1)},
-            new Object[]{"shirt", "cloth", 40d, 4l, 2023l, 1, 2, 6, LocalDate.of(2023, 6, 1)},
-            new Object[]{"shirt", "cloth", 50d, 5l, 2023l, 2, 3, 7, LocalDate.of(2023, 7, 1)},
-            new Object[]{"shirt", "cloth", 10d, 1l, 2023l, 2, 4, 10, LocalDate.of(2023, 10, 1)}
+            new Object[]{"bottle", "drink", 20d, 10L, 2023L, 1, 1, 1, LocalDate.of(2023, 1, 1)},
+            new Object[]{"bottle", "drink", 10d, 5L, 2023L, 1, 2, 4, LocalDate.of(2023, 4, 1)},
+            new Object[]{"bottle", "drink", 20d, 10L, 2023L, 2, 3, 8, LocalDate.of(2023, 8, 1)},
+            new Object[]{"bottle", "drink", 10d, 5L, 2023L, 2, 4, 12, LocalDate.of(2023, 12, 1)},
+
+            new Object[]{"cookie", "food", 60d, 20L, 2023L, 1, 1, 2, LocalDate.of(2023, 2, 1)},
+            new Object[]{"cookie", "food", 30d, 10L, 2023L, 1, 2, 5, LocalDate.of(2023, 5, 1)},
+            new Object[]{"cookie", "food", 15d, 5L, 2023L, 2, 3, 9, LocalDate.of(2023, 9, 1)},
+            new Object[]{"cookie", "food", 15d, 5L, 2023L, 2, 4, 11, LocalDate.of(2023, 11, 1)},
+
+            new Object[]{"shirt", "cloth", 20d, 2L, 2023L, 1, 1, 3, LocalDate.of(2023, 3, 1)},
+            new Object[]{"shirt", "cloth", 40d, 4L, 2023L, 1, 2, 6, LocalDate.of(2023, 6, 1)},
+            new Object[]{"shirt", "cloth", 50d, 5L, 2023L, 2, 3, 7, LocalDate.of(2023, 7, 1)},
+            new Object[]{"shirt", "cloth", 10d, 1L, 2023L, 2, 4, 10, LocalDate.of(2023, 10, 1)}
     ));
   }
 
   @Test
   void testCompareQuarterCurrentWithSamePreviousYear() {
-    Period.Quarter period = new Period.Quarter(tableField("quarter_sales"), tableField("year_sales"));
-    AggregatedMeasure sales = new AggregatedMeasure("sum(sales)", "sales", "sum");
+    Period.Quarter period = new Period.Quarter(this.quarter, this.year);
+    AggregatedMeasure sales = new AggregatedMeasure("sum(sales)", this.sales, "sum");
     ComparisonMeasureReferencePosition m = new ComparisonMeasureReferencePosition(
             "myMeasure",
             ABSOLUTE_DIFFERENCE,
@@ -105,48 +100,48 @@ public abstract class ATestPeriodComparison extends ABaseTestQuery {
             period);
 
     var query = Query.from(this.storeName)
-            .select(tableFields(List.of("year_sales", "quarter_sales")), List.of(m, sales))
+            .select(List.of(this.year, this.quarter), List.of(m, sales))
             .build();
 
     Table finalTable = this.executor.executeQuery(query);
     Assertions.assertThat(finalTable).containsExactlyInAnyOrder(
-            Arrays.asList(2022l, translate(1), null, 100d),
-            Arrays.asList(2022l, translate(2), null, 80d),
-            Arrays.asList(2022l, translate(3), null, 85d),
-            Arrays.asList(2022l, translate(4), null, 35d),
-            Arrays.asList(2023l, translate(1), 0d, 100d),
-            Arrays.asList(2023l, translate(2), 0d, 80d),
-            Arrays.asList(2023l, translate(3), 0d, 85d),
-            Arrays.asList(2023l, translate(4), 0d, 35d));
+            Arrays.asList(2022L, translate(1), null, 100d),
+            Arrays.asList(2022L, translate(2), null, 80d),
+            Arrays.asList(2022L, translate(3), null, 85d),
+            Arrays.asList(2022L, translate(4), null, 35d),
+            Arrays.asList(2023L, translate(1), 0d, 100d),
+            Arrays.asList(2023L, translate(2), 0d, 80d),
+            Arrays.asList(2023L, translate(3), 0d, 85d),
+            Arrays.asList(2023L, translate(4), 0d, 35d));
     Assertions.assertThat(finalTable.headers().stream().map(Header::name))
             .containsExactlyInAnyOrder(SqlUtils.squashqlExpression(period.year()), SqlUtils.squashqlExpression(period.quarter()), "myMeasure", "sum(sales)");
 
     // Add a condition and make sure condition is cleared during prefetching.s
     query = Query.from(this.storeName)
-            .where(tableField("year_sales"), eq(2023l))
-            .select(tableFields(List.of("year_sales", "quarter_sales")), List.of(m))
+            .where(criterion(this.year, eq(2023L)))
+            .select(List.of(this.year, this.quarter), List.of(m))
             .build();
     finalTable = this.executor.executeQuery(query);
     Assertions.assertThat(finalTable).containsExactlyInAnyOrder(
-            Arrays.asList(2023l, translate(1), 0d),
-            Arrays.asList(2023l, translate(2), 0d),
-            Arrays.asList(2023l, translate(3), 0d),
-            Arrays.asList(2023l, translate(4), 0d));
+            Arrays.asList(2023L, translate(1), 0d),
+            Arrays.asList(2023L, translate(2), 0d),
+            Arrays.asList(2023L, translate(3), 0d),
+            Arrays.asList(2023L, translate(4), 0d));
 
     query = Query.from(this.storeName)
-            .where(tableField("quarter_sales"), eq(1))
-            .select(tableFields(List.of("year_sales", "quarter_sales")), List.of(m))
+            .where(criterion(this.quarter, eq(1)))
+            .select(List.of(this.year, this.quarter), List.of(m))
             .build();
     finalTable = this.executor.executeQuery(query);
     Assertions.assertThat(finalTable).containsExactlyInAnyOrder(
-            Arrays.asList(2022l, translate(1), null),
-            Arrays.asList(2023l, translate(1), 0d));
+            Arrays.asList(2022L, translate(1), null),
+            Arrays.asList(2023L, translate(1), 0d));
   }
 
   @Test
   void testCompareQuarterCurrentWithPrevious() {
-    Period.Quarter period = new Period.Quarter(tableField("quarter_sales"), tableField("year_sales"));
-    AggregatedMeasure sales = new AggregatedMeasure("sum(sales)", "sales", "sum");
+    Period.Quarter period = new Period.Quarter(this.quarter, this.year);
+    AggregatedMeasure sales = new AggregatedMeasure("sum(sales)", this.sales, "sum");
     ComparisonMeasureReferencePosition m = new ComparisonMeasureReferencePosition(
             "myMeasure",
             ABSOLUTE_DIFFERENCE,
@@ -155,28 +150,28 @@ public abstract class ATestPeriodComparison extends ABaseTestQuery {
             period);
 
     var query = Query.from(this.storeName)
-            .select(tableFields(List.of("year_sales", "quarter_sales", SCENARIO_FIELD_NAME)), List.of(m, sales))
+            .select(List.of(this.year, this.quarter), List.of(m, sales))
             .build();
 
     Table finalTable = this.executor.executeQuery(query);
     Assertions.assertThat(finalTable).containsExactlyInAnyOrder(
-            Arrays.asList(2022l, translate(1), "base", null, 100d),
-            Arrays.asList(2022l, translate(2), "base", -20d, 80d),
-            Arrays.asList(2022l, translate(3), "base", 5d, 85d),
-            Arrays.asList(2022l, translate(4), "base", -50d, 35d),
-            Arrays.asList(2023l, translate(1), "base", 65d, 100d),
-            Arrays.asList(2023l, translate(2), "base", -20d, 80d),
-            Arrays.asList(2023l, translate(3), "base", 5d, 85d),
-            Arrays.asList(2023l, translate(4), "base", -50d, 35d));
+            Arrays.asList(2022L, translate(1), null, 100d),
+            Arrays.asList(2022L, translate(2), -20d, 80d),
+            Arrays.asList(2022L, translate(3), 5d, 85d),
+            Arrays.asList(2022L, translate(4), -50d, 35d),
+            Arrays.asList(2023L, translate(1), 65d, 100d),
+            Arrays.asList(2023L, translate(2), -20d, 80d),
+            Arrays.asList(2023L, translate(3), 5d, 85d),
+            Arrays.asList(2023L, translate(4), -50d, 35d));
     Assertions
             .assertThat(finalTable.headers().stream().map(Header::name))
-            .containsExactlyInAnyOrder(DataLoader.SCENARIO_FIELD_NAME, SqlUtils.squashqlExpression(period.year()), SqlUtils.squashqlExpression(period.quarter()), "myMeasure", "sum(sales)");
+            .containsExactlyInAnyOrder(SqlUtils.squashqlExpression(period.year()), SqlUtils.squashqlExpression(period.quarter()), "myMeasure", "sum(sales)");
   }
 
   @Test
   void testCompareYearCurrentWithPrevious() {
-    Period.Year period = new Period.Year(tableField("year_sales"));
-    AggregatedMeasure sales = new AggregatedMeasure("sum(sales)", "sales", "sum");
+    Period.Year period = new Period.Year(this.year);
+    AggregatedMeasure sales = new AggregatedMeasure("sum(sales)", this.sales, "sum");
     ComparisonMeasureReferencePosition m = new ComparisonMeasureReferencePosition(
             "myMeasure",
             ABSOLUTE_DIFFERENCE,
@@ -185,29 +180,27 @@ public abstract class ATestPeriodComparison extends ABaseTestQuery {
             period);
 
     var query = Query.from(this.storeName)
-            .select(tableFields(List.of("year_sales", SCENARIO_FIELD_NAME)), List.of(m, sales))
+            .select(List.of(this.year), List.of(m, sales))
             .build();
     Table finalTable = this.executor.executeQuery(query);
     Assertions.assertThat(finalTable).containsExactlyInAnyOrder(
-            Arrays.asList(2022l, "base", null, 300d),
-            Arrays.asList(2023l, "base", 0d, 300d));
+            Arrays.asList(2022L, null, 300d),
+            Arrays.asList(2023L, 0d, 300d));
     Assertions
             .assertThat(finalTable.headers().stream().map(Header::name))
-            .containsExactlyInAnyOrder(DataLoader.SCENARIO_FIELD_NAME, SqlUtils.squashqlExpression(period.year()), "myMeasure", "sum(sales)");
+            .containsExactlyInAnyOrder(SqlUtils.squashqlExpression(period.year()), "myMeasure", "sum(sales)");
 
     // Rollup will make Grand Total and Total appear. For this line, we can't make the comparison. Null should be
     // written and the query should not fail.
     query = Query.from(this.storeName)
-            .select(tableFields(List.of("year_sales", SCENARIO_FIELD_NAME)), List.of(m, sales))
-            .rollup(tableFields(List.of("year_sales", SCENARIO_FIELD_NAME)))
+            .select(List.of(this.year), List.of(m, sales))
+            .rollup(List.of(this.year))
             .build();
     finalTable = this.executor.executeQuery(query);
     Assertions.assertThat(finalTable).containsExactlyInAnyOrder(
-            Arrays.asList(GRAND_TOTAL, GRAND_TOTAL, null, 600d),
-            Arrays.asList(2022l, TOTAL, null, 300d),
-            Arrays.asList(2022l, "base", null, 300d),
-            Arrays.asList(2023l, TOTAL, 0d, 300d),
-            Arrays.asList(2023l, "base", 0d, 300d));
+            Arrays.asList(GRAND_TOTAL, null, 600d),
+            Arrays.asList(2022L, null, 300d),
+            Arrays.asList(2023L, 0d, 300d));
   }
 
   @Test
@@ -222,12 +215,12 @@ public abstract class ATestPeriodComparison extends ABaseTestQuery {
             period);
 
     var query = Query.from(this.storeName)
-            .select(List.of(year), List.of(m, sales))
+            .select(List.of(this.year), List.of(m, sales))
             .build();
     Table finalTable = this.executor.executeQuery(query);
     Assertions.assertThat(finalTable).containsExactlyInAnyOrder(
-            Arrays.asList(2022l, null, 300d),
-            Arrays.asList(2023l, 0d, 300d));
+            Arrays.asList(2022L, null, 300d),
+            Arrays.asList(2023L, 0d, 300d));
     Assertions
             .assertThat(finalTable.headers().stream().map(Header::name))
             .containsExactlyInAnyOrder(SqlUtils.squashqlExpression(period.year()), "myMeasure", "sum(sales)");
@@ -235,8 +228,8 @@ public abstract class ATestPeriodComparison extends ABaseTestQuery {
 
   @Test
   void testCompareSemesterCurrentWithPrevious() {
-    Period.Semester period = new Period.Semester(tableField("semester_sales"), tableField("year_sales"));
-    AggregatedMeasure sales = new AggregatedMeasure("sum(sales)", "sales", "sum");
+    Period.Semester period = new Period.Semester(this.semester, this.year);
+    AggregatedMeasure sales = new AggregatedMeasure("sum(sales)", this.sales, "sum");
     ComparisonMeasureReferencePosition m = new ComparisonMeasureReferencePosition(
             "myMeasure",
             ABSOLUTE_DIFFERENCE,
@@ -245,24 +238,24 @@ public abstract class ATestPeriodComparison extends ABaseTestQuery {
             period);
 
     var query = Query.from(this.storeName)
-            .select(tableFields(List.of("year_sales", "semester_sales", SCENARIO_FIELD_NAME)), List.of(m, sales))
+            .select(List.of(this.year, this.semester), List.of(m, sales))
             .build();
 
     Table finalTable = this.executor.executeQuery(query);
     Assertions.assertThat(finalTable).containsExactlyInAnyOrder(
-            Arrays.asList(2022l, translate(1), "base", null, 180d),
-            Arrays.asList(2022l, translate(2), "base", -60d, 120d),
-            Arrays.asList(2023l, translate(1), "base", 60d, 180d),
-            Arrays.asList(2023l, translate(2), "base", -60d, 120d));
+            Arrays.asList(2022L, translate(1), null, 180d),
+            Arrays.asList(2022L, translate(2), -60d, 120d),
+            Arrays.asList(2023L, translate(1), 60d, 180d),
+            Arrays.asList(2023L, translate(2), -60d, 120d));
     Assertions
             .assertThat(finalTable.headers().stream().map(Header::name))
-            .containsExactlyInAnyOrder(DataLoader.SCENARIO_FIELD_NAME, SqlUtils.squashqlExpression(period.year()), SqlUtils.squashqlExpression(period.semester()), "myMeasure", "sum(sales)");
+            .containsExactlyInAnyOrder(SqlUtils.squashqlExpression(period.year()), SqlUtils.squashqlExpression(period.semester()), "myMeasure", "sum(sales)");
   }
 
   @Test
   void testCompareMonthCurrentWithPrevious() {
-    Period.Month period = new Period.Month(tableField("month_sales"), tableField("year_sales"));
-    AggregatedMeasure sales = new AggregatedMeasure("sum(sales)", "sales", "sum");
+    Period.Month period = new Period.Month(this.month, this.year);
+    AggregatedMeasure sales = new AggregatedMeasure("sum(sales)", this.sales, "sum");
     ComparisonMeasureReferencePosition m = new ComparisonMeasureReferencePosition(
             "myMeasure",
             ABSOLUTE_DIFFERENCE,
@@ -272,29 +265,29 @@ public abstract class ATestPeriodComparison extends ABaseTestQuery {
     var query = Query.from(this.storeName)
             // Filter to limit the number of rows
             .where(Functions.all(
-                    criterion("year_sales", Functions.in(2022, 2023)),
-                    criterion("month_sales", Functions.in(1, 2, 12))
+                    criterion(this.year, Functions.in(2022, 2023)),
+                    criterion(this.month, Functions.in(1, 2, 12))
             ))
-            .select(tableFields(List.of("year_sales", "month_sales", SCENARIO_FIELD_NAME)), List.of(m, sales))
+            .select(List.of(this.year, this.month), List.of(m, sales))
             .build();
 
     Table finalTable = this.executor.executeQuery(query);
     Assertions.assertThat(finalTable).containsExactlyInAnyOrder(
-            Arrays.asList(2022l, translate(1), "base", null, 20d),
-            Arrays.asList(2022l, translate(2), "base", 40d, 60d),
-            Arrays.asList(2022l, translate(12), "base", -5d, 10d),
-            Arrays.asList(2023l, translate(1), "base", 10d, 20d),
-            Arrays.asList(2023l, translate(2), "base", 40d, 60d),
-            Arrays.asList(2023l, translate(12), "base", -5d, 10d));
+            Arrays.asList(2022L, translate(1), null, 20d),
+            Arrays.asList(2022L, translate(2), 40d, 60d),
+            Arrays.asList(2022L, translate(12), -5d, 10d),
+            Arrays.asList(2023L, translate(1), 10d, 20d),
+            Arrays.asList(2023L, translate(2), 40d, 60d),
+            Arrays.asList(2023L, translate(12), -5d, 10d));
     Assertions
             .assertThat(finalTable.headers().stream().map(Header::name))
-            .containsExactlyInAnyOrder(DataLoader.SCENARIO_FIELD_NAME, SqlUtils.squashqlExpression(period.year()), SqlUtils.squashqlExpression(period.month()), "myMeasure", "sum(sales)");
+            .containsExactlyInAnyOrder(SqlUtils.squashqlExpression(period.year()), SqlUtils.squashqlExpression(period.month()), "myMeasure", "sum(sales)");
   }
 
   @Test
   void testPeriodIsMissingFromQuery() {
-    Period.Year period = new Period.Year(tableField("year_sales"));
-    AggregatedMeasure sales = new AggregatedMeasure("sum(sales)", "sales", "sum");
+    Period.Year period = new Period.Year(this.year);
+    AggregatedMeasure sales = new AggregatedMeasure("sum(sales)", this.sales, "sum");
     ComparisonMeasureReferencePosition m = new ComparisonMeasureReferencePosition(
             "myMeasure",
             ABSOLUTE_DIFFERENCE,
@@ -303,7 +296,7 @@ public abstract class ATestPeriodComparison extends ABaseTestQuery {
             period);
 
     var query = Query.from(this.storeName)
-            .select(tableFields(List.of(SCENARIO_FIELD_NAME)), List.of(m))
+            .select(List.of(this.ean), List.of(m))
             .build();
     Assertions.assertThatThrownBy(() -> this.executor.executeQuery(query))
             .isInstanceOf(IllegalArgumentException.class)
@@ -324,8 +317,8 @@ public abstract class ATestPeriodComparison extends ABaseTestQuery {
    */
   @Test
   void testCompareYearCurrentWithPreviousWithFilterAndCalculatedMeasure() {
-    Period.Year period = new Period.Year(tableField("year_sales"));
-    AggregatedMeasure sales = new AggregatedMeasure("sum(sales)", "sales", "sum");
+    Period.Year period = new Period.Year(this.year);
+    AggregatedMeasure sales = new AggregatedMeasure("sum(sales)", this.sales, "sum");
     Measure multiply = Functions.multiply("sales times 2", sales, Functions.integer(2));
     ComparisonMeasureReferencePosition m = new ComparisonMeasureReferencePosition(
             "myMeasure",
@@ -335,18 +328,18 @@ public abstract class ATestPeriodComparison extends ABaseTestQuery {
             period);
 
     var query = Query.from(this.storeName)
-            .where(criterion("year_sales", eq(2023l)))
-            .select(tableFields(List.of("year_sales", SCENARIO_FIELD_NAME)), List.of(m, multiply))
+            .where(criterion(this.year, eq(2023L)))
+            .select(List.of(this.year), List.of(m, multiply))
             .build();
     Table finalTable = this.executor.executeQuery(query);
     Assertions.assertThat(finalTable).containsExactlyInAnyOrder(
-            Arrays.asList(2023l, "base", 0d, 600d));
+            Arrays.asList(2023L, 0d, 600d));
   }
 
   @Test
   void testCompareWithLimit() {
-    Period.Quarter period = new Period.Quarter(tableField("quarter_sales"), tableField("year_sales"));
-    AggregatedMeasure sales = new AggregatedMeasure("sum(sales)", "sales", "sum");
+    Period.Quarter period = new Period.Quarter(this.quarter, this.year);
+    AggregatedMeasure sales = new AggregatedMeasure("sum(sales)", this.sales, "sum");
     ComparisonMeasureReferencePosition m = new ComparisonMeasureReferencePosition(
             "myMeasure",
             ABSOLUTE_DIFFERENCE,
@@ -355,7 +348,7 @@ public abstract class ATestPeriodComparison extends ABaseTestQuery {
             period);
 
     var query = Query.from(this.storeName)
-            .select(tableFields(List.of("year_sales", "quarter_sales")), List.of(m, sales))
+            .select(List.of(this.year, this.quarter), List.of(m, sales))
             .limit(2)
             .build();
 
diff --git a/core/src/test/java/io/squashql/query/ATestQueryCache.java b/core/src/test/java/io/squashql/query/ATestQueryCache.java
index 9ba03fe..e76011b 100644
--- a/core/src/test/java/io/squashql/query/ATestQueryCache.java
+++ b/core/src/test/java/io/squashql/query/ATestQueryCache.java
@@ -46,6 +46,7 @@ public abstract class ATestQueryCache extends ABaseTestQuery {
 
   @Override
   protected Map<String, List<TableTypedField>> getFieldsByStore() {
+    TableTypedField scenario = new TableTypedField(this.storeName, "scenario", String.class);
     TableTypedField ean = new TableTypedField(this.storeName, "ean", String.class);
     TableTypedField category = new TableTypedField(this.storeName, "category", String.class);
     TableTypedField price = new TableTypedField(this.storeName, "price", double.class);
@@ -56,7 +57,7 @@ public abstract class ATestQueryCache extends ABaseTestQuery {
     TableTypedField comp_price = new TableTypedField(this.competitorStoreName, "comp_price", double.class);
 
     return Map.of(
-            this.storeName, List.of(ean, category, price, qty),
+            this.storeName, List.of(scenario, ean, category, price, qty),
             this.competitorStoreName, List.of(comp_ean, comp_name, comp_price),
             this.other, List.of(ean, category, price)
     );
@@ -65,9 +66,9 @@ public abstract class ATestQueryCache extends ABaseTestQuery {
   @Override
   protected void loadData() {
     this.tm.load(this.storeName, List.of(
-            new Object[]{"bottle", "drink", 2d, 10},
-            new Object[]{"cookie", "food", 3d, 20},
-            new Object[]{"shirt", "cloth", 10d, 3}
+            new Object[]{"base", "bottle", "drink", 2d, 10},
+            new Object[]{"base", "cookie", "food", 3d, 20},
+            new Object[]{"base", "shirt", "cloth", 10d, 3}
     ));
 
     this.tm.load(this.competitorStoreName, List.of(
@@ -99,13 +100,13 @@ public abstract class ATestQueryCache extends ABaseTestQuery {
             .select(tableFields(List.of(SCENARIO_FIELD_NAME)), List.of(sum("ps", "price"), sum("qs", "quantity")))
             .build();
     Table result = this.executor.executeQuery(query);
-    Assertions.assertThat(result).containsExactlyInAnyOrder(List.of("base", 15.0d, 33l));
+    Assertions.assertThat(result).containsExactlyInAnyOrder(List.of("base", 15.0d, 33L));
     assertCacheStats(0, 3);
 
     // Execute the same
     result = this.executor.executeQuery(query);
     assertCacheStats(3, 3);
-    Assertions.assertThat(result).containsExactlyInAnyOrder(List.of("base", 15.0d, 33l));
+    Assertions.assertThat(result).containsExactlyInAnyOrder(List.of("base", 15.0d, 33L));
 
     // New query but same columns, same measure
     query = Query
@@ -113,7 +114,7 @@ public abstract class ATestQueryCache extends ABaseTestQuery {
             .select(tableFields(List.of(SCENARIO_FIELD_NAME)), List.of(sum("qs", "quantity")))
             .build();
     result = this.executor.executeQuery(query);
-    Assertions.assertThat(result).containsExactlyInAnyOrder(List.of("base", 33l));
+    Assertions.assertThat(result).containsExactlyInAnyOrder(List.of("base", 33L));
     assertCacheStats(5, 3);
   }
 
@@ -351,7 +352,7 @@ public abstract class ATestQueryCache extends ABaseTestQuery {
             .select(tableFields(List.of(SCENARIO_FIELD_NAME)), List.of(sum("ps", "price"), sum("qs", "quantity")))
             .build();
     Table result = execute(this.executor, query, paul);
-    Assertions.assertThat(result).containsExactlyInAnyOrder(List.of("base", 15.0d, 33l));
+    Assertions.assertThat(result).containsExactlyInAnyOrder(List.of("base", 15.0d, 33L));
     assertCacheStats(0, 3, paul);
     assertCacheStats(0, 0, peter);
 
@@ -359,13 +360,13 @@ public abstract class ATestQueryCache extends ABaseTestQuery {
     result = execute(this.executor, query, paul);
     assertCacheStats(3, 3, paul);
     assertCacheStats(0, 0, peter);
-    Assertions.assertThat(result).containsExactlyInAnyOrder(List.of("base", 15.0d, 33l));
+    Assertions.assertThat(result).containsExactlyInAnyOrder(List.of("base", 15.0d, 33L));
 
     // Execute the same query, but different user
     result = execute(this.executor, query, peter);
     assertCacheStats(0, 3, peter);
     assertCacheStats(3, 3, paul);
-    Assertions.assertThat(result).containsExactlyInAnyOrder(List.of("base", 15.0d, 33l));
+    Assertions.assertThat(result).containsExactlyInAnyOrder(List.of("base", 15.0d, 33L));
 
     /// Test invalid cache for a given user
     query.withParameter(QueryCacheParameter.KEY, new QueryCacheParameter(QueryCacheParameter.Action.INVALIDATE));
diff --git a/core/src/test/java/io/squashql/query/ATestQueryExecutor.java b/core/src/test/java/io/squashql/query/ATestQueryExecutor.java
index ae7cd50..58fab0f 100644
--- a/core/src/test/java/io/squashql/query/ATestQueryExecutor.java
+++ b/core/src/test/java/io/squashql/query/ATestQueryExecutor.java
@@ -35,6 +35,7 @@ public abstract class ATestQueryExecutor extends ABaseTestQuery {
 
   @Override
   protected Map<String, List<TableTypedField>> getFieldsByStore() {
+    TableTypedField scenario = new TableTypedField(this.storeName, "scenario", String.class);
     TableTypedField ean = new TableTypedField(this.storeName, "ean", String.class);
     TableTypedField eanId = new TableTypedField(this.storeName, "eanId", int.class);
     TableTypedField category = new TableTypedField(this.storeName, "category", String.class);
@@ -42,27 +43,27 @@ public abstract class ATestQueryExecutor extends ABaseTestQuery {
     TableTypedField price = new TableTypedField(this.storeName, "price", double.class);
     TableTypedField qty = new TableTypedField(this.storeName, "quantity", int.class);
     TableTypedField isFood = new TableTypedField(this.storeName, "isFood", boolean.class);
-    return Map.of(this.storeName, List.of(eanId, ean, category, subcategory, price, qty, isFood));
+    return Map.of(this.storeName, List.of(scenario, eanId, ean, category, subcategory, price, qty, isFood));
   }
 
   @Override
   protected void loadData() {
-    this.tm.load(MAIN_SCENARIO_NAME, this.storeName, List.of(
-            new Object[]{0, "starbuck's coffee", "drink", null, 2d, 10, true}, // use a string with '
-            new Object[]{1, "cookie", "food", "biscuit", 3d, 20, true},
-            new Object[]{2, "shirt", "cloth", null, 10d, 3, false}
+    this.tm.load(this.storeName, List.of(
+            new Object[]{MAIN_SCENARIO_NAME, 0, "starbuck's coffee", "drink", null, 2d, 10, true}, // use a string with '
+            new Object[]{MAIN_SCENARIO_NAME, 1, "cookie", "food", "biscuit", 3d, 20, true},
+            new Object[]{MAIN_SCENARIO_NAME, 2, "shirt", "cloth", null, 10d, 3, false}
     ));
 
-    this.tm.load("s1", this.storeName, List.of(
-            new Object[]{0, "starbuck's coffee", "drink", null, 4d, 10, true},
-            new Object[]{1, "cookie", "food", "biscuit", 3d, 20, true},
-            new Object[]{2, "shirt", "cloth", null, 10d, 3, false}
+    this.tm.load(this.storeName, List.of(
+            new Object[]{"s1", 0, "starbuck's coffee", "drink", null, 4d, 10, true},
+            new Object[]{"s1", 1, "cookie", "food", "biscuit", 3d, 20, true},
+            new Object[]{"s1", 2, "shirt", "cloth", null, 10d, 3, false}
     ));
 
-    this.tm.load("s2", this.storeName, List.of(
-            new Object[]{0, "starbuck's coffee", "drink", null, 1.5d, 10, true},
-            new Object[]{1, "cookie", "food", "biscuit", 3d, 20, true},
-            new Object[]{2, "shirt", "cloth", null, 10d, 3, false}
+    this.tm.load(this.storeName, List.of(
+            new Object[]{"s2", 0, "starbuck's coffee", "drink", null, 1.5d, 10, true},
+            new Object[]{"s2", 1, "cookie", "food", "biscuit", 3d, 20, true},
+            new Object[]{"s2", 2, "shirt", "cloth", null, 10d, 3, false}
     ));
   }
 
diff --git a/core/src/test/java/io/squashql/query/ATestQueryExecutorWithJoins.java b/core/src/test/java/io/squashql/query/ATestQueryExecutorWithJoins.java
index 6f16dea..d8693b5 100644
--- a/core/src/test/java/io/squashql/query/ATestQueryExecutorWithJoins.java
+++ b/core/src/test/java/io/squashql/query/ATestQueryExecutorWithJoins.java
@@ -1,9 +1,5 @@
 package io.squashql.query;
 
-import static io.squashql.query.Functions.criterion;
-import static io.squashql.query.TableField.tableFields;
-import static io.squashql.transaction.DataLoader.MAIN_SCENARIO_NAME;
-
 import io.squashql.query.builder.Query;
 import io.squashql.query.database.QueryEngine;
 import io.squashql.query.dto.ConditionType;
@@ -12,16 +8,20 @@ import io.squashql.query.dto.QueryDto;
 import io.squashql.store.Datastore;
 import io.squashql.table.Table;
 import io.squashql.transaction.DataLoader;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.List;
 import java.util.function.Function;
-import org.assertj.core.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInstance;
+
+import static io.squashql.query.Functions.criterion;
+import static io.squashql.query.TableField.tableFields;
 
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 public abstract class ATestQueryExecutorWithJoins {
@@ -64,11 +64,11 @@ public abstract class ATestQueryExecutorWithJoins {
     this.datastore = createDatastore();
     this.tm = createDataLoader();
 
-    this.tm.loadCsv(MAIN_SCENARIO_NAME, this.orders, pathFunction.apply("orders.csv").toString(), delimiter, header);
-    this.tm.loadCsv(MAIN_SCENARIO_NAME, this.shippers, pathFunction.apply("shippers.csv").toString(), delimiter, header);
-    this.tm.loadCsv(MAIN_SCENARIO_NAME, this.products, pathFunction.apply("products.csv").toString(), delimiter, header);
-    this.tm.loadCsv(MAIN_SCENARIO_NAME, this.orderDetails, pathFunction.apply("order_details.csv").toString(), delimiter, header);
-    this.tm.loadCsv(MAIN_SCENARIO_NAME, this.categories, pathFunction.apply("categories.csv").toString(), delimiter, header);
+    this.tm.loadCsv(this.orders, pathFunction.apply("orders.csv").toString(), delimiter, header);
+    this.tm.loadCsv(this.shippers, pathFunction.apply("shippers.csv").toString(), delimiter, header);
+    this.tm.loadCsv(this.products, pathFunction.apply("products.csv").toString(), delimiter, header);
+    this.tm.loadCsv(this.orderDetails, pathFunction.apply("order_details.csv").toString(), delimiter, header);
+    this.tm.loadCsv(this.categories, pathFunction.apply("categories.csv").toString(), delimiter, header);
 
     this.queryExecutor = new QueryExecutor(createQueryEngine(this.datastore));
   }
diff --git a/core/src/test/java/io/squashql/query/ATestQueryWithJoins.java b/core/src/test/java/io/squashql/query/ATestQueryWithJoins.java
index 4a2e116..e35f8ab 100644
--- a/core/src/test/java/io/squashql/query/ATestQueryWithJoins.java
+++ b/core/src/test/java/io/squashql/query/ATestQueryWithJoins.java
@@ -1,9 +1,5 @@
 package io.squashql.query;
 
-import static io.squashql.query.Functions.criterion;
-import static io.squashql.query.TableField.tableFields;
-import static io.squashql.transaction.DataLoader.MAIN_SCENARIO_NAME;
-
 import io.squashql.TestClass;
 import io.squashql.query.builder.Query;
 import io.squashql.query.dto.ConditionType;
@@ -12,13 +8,17 @@ import io.squashql.query.dto.QueryDto;
 import io.squashql.table.Table;
 import io.squashql.type.TableTypedField;
 import io.squashql.util.TestUtil;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
 import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestInstance;
 
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+import static io.squashql.query.Functions.criterion;
+import static io.squashql.query.TableField.tableFields;
+
 @TestClass
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 public abstract class ATestQueryWithJoins extends ABaseTestQuery {
@@ -55,12 +55,12 @@ public abstract class ATestQueryWithJoins extends ABaseTestQuery {
 
   @Override
   protected void loadData() {
-    this.tm.load(MAIN_SCENARIO_NAME, this.orders, List.of(
+    this.tm.load(this.orders, List.of(
             new Object[]{0, 100},
             new Object[]{1, 101},
             new Object[]{2, 102}
     ));
-    this.tm.load(MAIN_SCENARIO_NAME, this.orderDetails, List.of(
+    this.tm.load(this.orderDetails, List.of(
             new Object[]{10, 0, 1001, 1},
             new Object[]{11, 0, 1002, 4},
             new Object[]{11, 0, 1003, 2},
@@ -68,12 +68,12 @@ public abstract class ATestQueryWithJoins extends ABaseTestQuery {
             new Object[]{13, 1, 1005, 1},
             new Object[]{14, 2, 1006, 8}
     ));
-    this.tm.load(MAIN_SCENARIO_NAME, this.shippers, List.of(
+    this.tm.load(this.shippers, List.of(
             new Object[]{100, "Speedy Express"},
             new Object[]{101, "United Package"},
             new Object[]{102, "Federal Shipping"}
     ));
-    this.tm.load(MAIN_SCENARIO_NAME, this.products, List.of(
+    this.tm.load(this.products, List.of(
             new Object[]{1001, "Chang", 10_001, 18d},
             new Object[]{1002, "Aniseed Syrup", 10_002, 20d},
             new Object[]{1003, "Genen Shouyu", 10_002, 4d},
@@ -81,7 +81,7 @@ public abstract class ATestQueryWithJoins extends ABaseTestQuery {
             new Object[]{1005, "Pavlova", 10_003, 6d},
             new Object[]{1006, "Camembert Pierrot", 10_004, 20d}
     ));
-    this.tm.load(MAIN_SCENARIO_NAME, this.categories, List.of(
+    this.tm.load(this.categories, List.of(
             new Object[]{10_001, "Beverages"},
             new Object[]{10_002, "Condiments"},
             new Object[]{10_003, "Confections"},
diff --git a/core/src/test/java/io/squashql/query/ATestSubQuery.java b/core/src/test/java/io/squashql/query/ATestSubQuery.java
index fbb83d2..754c7dd 100644
--- a/core/src/test/java/io/squashql/query/ATestSubQuery.java
+++ b/core/src/test/java/io/squashql/query/ATestSubQuery.java
@@ -17,7 +17,6 @@ import java.util.Map;
 import static io.squashql.query.Functions.*;
 import static io.squashql.query.agg.AggregationFunction.AVG;
 import static io.squashql.query.database.QueryEngine.GRAND_TOTAL;
-import static io.squashql.transaction.DataLoader.MAIN_SCENARIO_NAME;
 
 @TestClass
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@@ -41,7 +40,7 @@ public abstract class ATestSubQuery extends ABaseTestQuery {
 
   @Override
   protected void loadData() {
-    this.tm.load(MAIN_SCENARIO_NAME, this.store, List.of(
+    this.tm.load(this.store, List.of(
             new Object[]{"group a", "Paul", "sql", 50},
             new Object[]{"group a", "Paul", "java", 70},
             new Object[]{"group a", "Peter", "sql", 45},
diff --git a/core/src/test/java/io/squashql/query/TestMeasures.java b/core/src/test/java/io/squashql/query/TestMeasures.java
index 51d86ad..f8cafbf 100644
--- a/core/src/test/java/io/squashql/query/TestMeasures.java
+++ b/core/src/test/java/io/squashql/query/TestMeasures.java
@@ -17,7 +17,7 @@ public class TestMeasures {
 
   @Test
   void testAggregatedMeasureConstructor() {
-    Assertions.assertThatThrownBy(() -> new AggregatedMeasure("null", null, AggregationFunction.SUM))
+    Assertions.assertThatThrownBy(() -> new AggregatedMeasure("null", (Field) null, AggregationFunction.SUM))
             .isInstanceOf(NullPointerException.class);
     Assertions.assertThatThrownBy(() -> new AggregatedMeasure("null", "field", null))
             .isInstanceOf(NullPointerException.class);
diff --git a/server/src/test/java/io/squashql/spring/dataset/DatasetTestConfig.java b/server/src/test/java/io/squashql/spring/dataset/DatasetTestConfig.java
index 6a7cf10..d8dc038 100644
--- a/server/src/test/java/io/squashql/spring/dataset/DatasetTestConfig.java
+++ b/server/src/test/java/io/squashql/spring/dataset/DatasetTestConfig.java
@@ -88,6 +88,7 @@ public class DatasetTestConfig {
   }
 
   public static DuckDBDatastore createTestDatastoreWithData() {
+    TableTypedField scenario = new TableTypedField("our_prices", "scenario", String.class);
     TableTypedField ean = new TableTypedField("our_prices", "ean", String.class);
     TableTypedField pdv = new TableTypedField("our_prices", "pdv", String.class);
     TableTypedField price = new TableTypedField("our_prices", "price", double.class);
@@ -100,7 +101,7 @@ public class DatasetTestConfig {
     TableTypedField compConcurrentEan = new TableTypedField("their_prices", "competitor_concurrent_ean", String.class);
     TableTypedField compPrice = new TableTypedField("their_prices", "competitor_price", double.class);
 
-    Store our_price_store = new Store("our_prices", List.of(ean, pdv, price, qty, capdv));
+    Store our_price_store = new Store("our_prices", List.of(scenario, ean, pdv, price, qty, capdv));
     Store their_prices_store = new Store("their_prices", List.of(compEan, compConcurrentPdv, compBrand,
             compConcurrentEan, compPrice));
     Store our_stores_their_stores_store = new Store("our_stores_their_stores", List.of(
@@ -112,44 +113,39 @@ public class DatasetTestConfig {
     DuckDBDataLoader tm = new DuckDBDataLoader(datastore);
 
     tm.createOrReplaceTable(our_price_store.name(), our_price_store.fields());
-    tm.createOrReplaceTable(their_prices_store.name(), their_prices_store.fields(), false);
-    tm.createOrReplaceTable(our_stores_their_stores_store.name(), our_stores_their_stores_store.fields(), false);
-
-    tm.load(MAIN_SCENARIO_NAME,
-            "our_prices", List.of(
-                    new Object[]{"Nutella 250g", "ITM Balma", 10d, 1000, 10_000d},
-                    new Object[]{"ITMella 250g", "ITM Balma", 10d, 1000, 10_000d},
-                    new Object[]{"Nutella 250g", "ITM Toulouse and Drive", 10d, 1000, 10_000d},
-                    new Object[]{"ITMella 250g", "ITM Toulouse and Drive", 10d, 1000, 10_000d}
-            ));
-    tm.load("MN up",
-            "our_prices", List.of(
-                    new Object[]{"Nutella 250g", "ITM Balma", 11d, 1000, 11_000d},
-                    new Object[]{"ITMella 250g", "ITM Balma", 10d, 1000, 10_000d},
-                    new Object[]{"Nutella 250g", "ITM Toulouse and Drive", 11d, 1000, 11_000d},
-                    new Object[]{"ITMella 250g", "ITM Toulouse and Drive", 10d, 1000, 10_000d}
-            ));
-    tm.load("MDD up",
-            "our_prices", List.of(
-                    new Object[]{"Nutella 250g", "ITM Balma", 10d, 1000, 10_000d},
-                    new Object[]{"ITMella 250g", "ITM Balma", 11d, 1000, 11_000d},
-                    new Object[]{"Nutella 250g", "ITM Toulouse and Drive", 10d, 1000, 10_000d},
-                    new Object[]{"ITMella 250g", "ITM Toulouse and Drive", 11d, 1000, 11_000d}
-            ));
-    tm.load("MN & MDD up",
-            "our_prices", List.of(
-                    new Object[]{"Nutella 250g", "ITM Balma", 11d, 1000, 11_000d},
-                    new Object[]{"ITMella 250g", "ITM Balma", 11d, 1000, 11_000d},
-                    new Object[]{"Nutella 250g", "ITM Toulouse and Drive", 11d, 1000, 11_000d},
-                    new Object[]{"ITMella 250g", "ITM Toulouse and Drive", 11d, 1000, 11_000d}
-            ));
-    tm.load("MN & MDD down",
-            "our_prices", List.of(
-                    new Object[]{"Nutella 250g", "ITM Balma", 9d, 1000, 9_000d},
-                    new Object[]{"ITMella 250g", "ITM Balma", 9d, 1000, 9_000d},
-                    new Object[]{"Nutella 250g", "ITM Toulouse and Drive", 9d, 1000, 9_000d},
-                    new Object[]{"ITMella 250g", "ITM Toulouse and Drive", 9d, 1000, 9_000d}
-            ));
+    tm.createOrReplaceTable(their_prices_store.name(), their_prices_store.fields());
+    tm.createOrReplaceTable(our_stores_their_stores_store.name(), our_stores_their_stores_store.fields());
+
+    tm.load("our_prices", List.of(
+            new Object[]{MAIN_SCENARIO_NAME, "Nutella 250g", "ITM Balma", 10d, 1000, 10_000d},
+            new Object[]{MAIN_SCENARIO_NAME, "ITMella 250g", "ITM Balma", 10d, 1000, 10_000d},
+            new Object[]{MAIN_SCENARIO_NAME, "Nutella 250g", "ITM Toulouse and Drive", 10d, 1000, 10_000d},
+            new Object[]{MAIN_SCENARIO_NAME, "ITMella 250g", "ITM Toulouse and Drive", 10d, 1000, 10_000d}
+    ));
+    tm.load("our_prices", List.of(
+            new Object[]{"MN up", "Nutella 250g", "ITM Balma", 11d, 1000, 11_000d},
+            new Object[]{"MN up", "ITMella 250g", "ITM Balma", 10d, 1000, 10_000d},
+            new Object[]{"MN up", "Nutella 250g", "ITM Toulouse and Drive", 11d, 1000, 11_000d},
+            new Object[]{"MN up", "ITMella 250g", "ITM Toulouse and Drive", 10d, 1000, 10_000d}
+    ));
+    tm.load("our_prices", List.of(
+            new Object[]{"MDD up", "Nutella 250g", "ITM Balma", 10d, 1000, 10_000d},
+            new Object[]{"MDD up", "ITMella 250g", "ITM Balma", 11d, 1000, 11_000d},
+            new Object[]{"MDD up", "Nutella 250g", "ITM Toulouse and Drive", 10d, 1000, 10_000d},
+            new Object[]{"MDD up", "ITMella 250g", "ITM Toulouse and Drive", 11d, 1000, 11_000d}
+    ));
+    tm.load("our_prices", List.of(
+            new Object[]{"MN & MDD up", "Nutella 250g", "ITM Balma", 11d, 1000, 11_000d},
+            new Object[]{"MN & MDD up", "ITMella 250g", "ITM Balma", 11d, 1000, 11_000d},
+            new Object[]{"MN & MDD up", "Nutella 250g", "ITM Toulouse and Drive", 11d, 1000, 11_000d},
+            new Object[]{"MN & MDD up", "ITMella 250g", "ITM Toulouse and Drive", 11d, 1000, 11_000d}
+    ));
+    tm.load("our_prices", List.of(
+            new Object[]{"MN & MDD down", "Nutella 250g", "ITM Balma", 9d, 1000, 9_000d},
+            new Object[]{"MN & MDD down", "ITMella 250g", "ITM Balma", 9d, 1000, 9_000d},
+            new Object[]{"MN & MDD down", "Nutella 250g", "ITM Toulouse and Drive", 9d, 1000, 9_000d},
+            new Object[]{"MN & MDD down", "ITMella 250g", "ITM Toulouse and Drive", 9d, 1000, 9_000d}
+    ));
 
     tm.load("their_prices", List.of(
             new Object[]{"Nutella 250g", "Leclerc Rouffiac", "Leclerc", "Nutella 250g", 9d},
diff --git a/spark/src/test/java/io/squashql/data/TestLoadingFromCSV.java b/spark/src/test/java/io/squashql/data/TestLoadingFromCSV.java
index 9d5af0a..e75cf94 100644
--- a/spark/src/test/java/io/squashql/data/TestLoadingFromCSV.java
+++ b/spark/src/test/java/io/squashql/data/TestLoadingFromCSV.java
@@ -2,7 +2,6 @@ package io.squashql.data;
 
 import io.squashql.SparkDatastore;
 import io.squashql.transaction.SparkDataLoader;
-import io.squashql.transaction.DataLoader;
 import org.apache.spark.sql.Dataset;
 import org.apache.spark.sql.Row;
 import org.assertj.core.api.Assertions;
@@ -17,7 +16,7 @@ import java.util.function.Function;
 
 public class TestLoadingFromCSV {
 
-  private static Function<String, Path> pathFunction = fileName -> {
+  private static final Function<String, Path> pathFunction = fileName -> {
     URL resource = Thread.currentThread().getContextClassLoader().getResource(fileName);
     try {
       if (resource == null) {
@@ -40,14 +39,14 @@ public class TestLoadingFromCSV {
     SparkDatastore datastore = new SparkDatastore();
     SparkDataLoader tm = new SparkDataLoader(datastore.spark);
 
-    tm.loadCsv(DataLoader.MAIN_SCENARIO_NAME, customersStore, pathFunction.apply("customers.csv").toString(), delimiter, header);
-    tm.loadCsv(DataLoader.MAIN_SCENARIO_NAME, ordersStore, pathFunction.apply("orders.csv").toString(), delimiter, header);
+    tm.loadCsv(customersStore, pathFunction.apply("customers.csv").toString(), delimiter, header);
+    tm.loadCsv(ordersStore, pathFunction.apply("orders.csv").toString(), delimiter, header);
 
     Dataset<Row> customersDS = datastore.get(customersStore);
     Dataset<Row> ordersDS = datastore.get(ordersStore);
     Assertions.assertThat(customersDS.count()).isEqualTo(91);
-    Assertions.assertThat(customersDS.columns().length).isEqualTo(7 + 1); // +1 because of scenario
+    Assertions.assertThat(customersDS.columns().length).isEqualTo(7);
     Assertions.assertThat(ordersDS.count()).isEqualTo(196);
-    Assertions.assertThat(ordersDS.columns().length).isEqualTo(5 + 1);  // +1 because of scenario
+    Assertions.assertThat(ordersDS.columns().length).isEqualTo(5);
   }
 }
diff --git a/spark/src/test/java/io/squashql/remote/TestQueryRemote.java b/spark/src/test/java/io/squashql/remote/TestQueryRemote.java
index 7388b78..eba8185 100644
--- a/spark/src/test/java/io/squashql/remote/TestQueryRemote.java
+++ b/spark/src/test/java/io/squashql/remote/TestQueryRemote.java
@@ -89,22 +89,23 @@ public class TestQueryRemote {
     QueryExecutor executor = new QueryExecutor(new SparkQueryEngine(datastore));
     SparkDataLoader tm = new SparkDataLoader(datastore.spark);
 
+    TableTypedField scenario = new TableTypedField(storeName, "scenario", String.class);
     TableTypedField ean = new TableTypedField(storeName, "ean", String.class);
     TableTypedField category = new TableTypedField(storeName, "category", String.class);
     TableTypedField price = new TableTypedField(storeName, "price", double.class);
     TableTypedField qty = new TableTypedField(storeName, "quantity", int.class);
     tm.createTemporaryTable(storeName, List.of(ean, category, price, qty));
 
-    tm.load(MAIN_SCENARIO_NAME, storeName, List.of(
-            new Object[]{"bottle", "drink", 2d, 10},
-            new Object[]{"cookie", "food", 3d, 20},
-            new Object[]{"shirt", "cloth", 10d, 3}
+    tm.load(storeName, List.of(
+            new Object[]{MAIN_SCENARIO_NAME, "bottle", "drink", 2d, 10},
+            new Object[]{MAIN_SCENARIO_NAME, "cookie", "food", 3d, 20},
+            new Object[]{MAIN_SCENARIO_NAME, "shirt", "cloth", 10d, 3}
     ));
 
-    tm.load("s1", storeName, List.of(
-            new Object[]{"bottle", "drink", 4d, 10},
-            new Object[]{"cookie", "food", 3d, 20},
-            new Object[]{"shirt", "cloth", 10d, 3}
+    tm.load(storeName, List.of(
+            new Object[]{"s1", "bottle", "drink", 4d, 10},
+            new Object[]{"s1", "cookie", "food", 3d, 20},
+            new Object[]{"s1", "shirt", "cloth", 10d, 3}
     ));
 
     QueryDto query = new QueryDto()