This is an automated email from the ASF dual-hosted git repository. bchapuis pushed a commit to branch calcite-framework in repository https://gitbox.apache.org/repos/asf/incubator-baremaps.git
commit 14d2eb9ddeae793655cecf7368c760f027b0ac66 Author: Bertil Chapuis <[email protected]> AuthorDate: Tue Jan 14 21:08:02 2025 +0100 Add list --- .../apache/baremaps/data/calcite/CalciteTest.java | 157 +++++++++++++++++---- 1 file changed, 130 insertions(+), 27 deletions(-) diff --git a/baremaps-data/src/test/java/org/apache/baremaps/data/calcite/CalciteTest.java b/baremaps-data/src/test/java/org/apache/baremaps/data/calcite/CalciteTest.java index 52768a70d..9e7fc96d6 100644 --- a/baremaps-data/src/test/java/org/apache/baremaps/data/calcite/CalciteTest.java +++ b/baremaps-data/src/test/java/org/apache/baremaps/data/calcite/CalciteTest.java @@ -24,28 +24,56 @@ import org.apache.baremaps.data.type.RowDataType; import org.apache.baremaps.store.DataColumn.Cardinality; import org.apache.baremaps.store.DataColumn.Type; import org.apache.baremaps.store.*; +import org.apache.calcite.DataContext; +import org.apache.calcite.DataContexts; +import org.apache.calcite.adapter.enumerable.EnumerableConvention; +import org.apache.calcite.adapter.enumerable.EnumerableInterpreter; import org.apache.calcite.config.Lex; +import org.apache.calcite.interpreter.Interpreter; import org.apache.calcite.jdbc.CalciteConnection; +import org.apache.calcite.linq4j.Enumerable; +import org.apache.calcite.linq4j.Linq4j; import org.apache.calcite.model.ModelHandler; +import org.apache.calcite.plan.RelOptCluster; +import org.apache.calcite.plan.RelOptPlanner; +import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.plan.volcano.VolcanoPlanner; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rex.RexBuilder; import org.apache.calcite.runtime.SpatialTypeFunctions; +import org.apache.calcite.schema.ScannableTable; import org.apache.calcite.schema.SchemaPlus; -import org.apache.calcite.schema.impl.ViewTable; -import org.apache.calcite.schema.impl.ViewTableMacro; +import org.apache.calcite.schema.Table; +import org.apache.calcite.schema.impl.*; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlNodeList; import org.apache.calcite.sql.fun.SqlSpatialTypeFunctions; import org.apache.calcite.sql.parser.SqlParseException; import org.apache.calcite.sql.parser.SqlParser; import org.apache.calcite.sql.parser.ddl.SqlDdlParserImpl; +import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.sql.validate.SqlConformanceEnum; +import org.apache.calcite.tools.FrameworkConfig; +import org.apache.calcite.tools.Frameworks; +import org.apache.calcite.tools.Planner; import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; +import org.apache.calcite.adapter.enumerable.EnumerableRel; +import org.apache.calcite.adapter.enumerable.EnumerableInterpreter; +import org.apache.calcite.adapter.enumerable.EnumerableRelImplementor; +import org.apache.calcite.linq4j.Enumerator; +import org.apache.calcite.plan.*; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.schema.SchemaPlus; +import org.apache.calcite.tools.*; import java.sql.*; -import java.util.Collections; -import java.util.List; -import java.util.Properties; +import java.util.*; public class CalciteTest { @@ -102,13 +130,14 @@ public class CalciteTest { "FROM city c " + // lowercase and unquoted "JOIN population p ON c.id = p.city_id"; - ViewTableMacro materializedView = ViewTable.viewMacro( + ViewTableMacro materializedView = MaterializedViewTable.viewMacro( rootSchema, mvSql, Collections.emptyList(), // Schema path List.of("city_population"), // Name parts false); // Not a materialized view + rootSchema.add("city_population", materializedView); // Debug: List all tables in the root schema @@ -121,7 +150,7 @@ public class CalciteTest { try (Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(sql)) { while (resultSet.next()) { - System.out.println(resultSet.getString("id") + " " + resultSet.getString("name")); + System.out.println(resultSet.getString("id") + " " + resultSet.getString("geometry")); } } @@ -139,32 +168,106 @@ public class CalciteTest { } + public class ListTable extends AbstractTable implements ScannableTable { + private final List<Integer> data; + + public ListTable(List<Integer> data) { + this.data = data; + } + + @Override + public RelDataType getRowType(RelDataTypeFactory typeFactory) { + // Define a single column named "value" of type INTEGER + return typeFactory.builder() + .add("V", SqlTypeName.INTEGER) + .build(); + } + + @Override + public Enumerable<Object[]> scan(DataContext root) { + // Convert the List<Integer> to Enumerable<Object[]> + return Linq4j.asEnumerable(data) + .select(i -> new Object[]{i}); + } + } + + public class ListSchema extends AbstractSchema { + private final List<Integer> listA; + private final List<Integer> listB; + + public ListSchema(List<Integer> listA, List<Integer> listB) { + this.listA = listA; + this.listB = listB; + } + + @Override + protected Map<String, Table> getTableMap() { + Map<String, Table> tables = new HashMap<>(); + tables.put("LIST_A", new ListTable(listA)); + tables.put("LIST_B", new ListTable(listB)); // Initially empty + return tables; + } + } + @Test - void ddl() throws SqlParseException { - - // Example SQL script with multiple DDL statements - String sqlScript = """ - CREATE MATERIALIZED VIEW IF NOT EXISTS my_view AS - SELECT * FROM my_table; - """; - - // Build a parser config that supports DDL - SqlParser.Config config = SqlParser.configBuilder() - .setParserFactory(SqlDdlParserImpl.FACTORY) - .setConformance(SqlConformanceEnum.BABEL) - .setLex(Lex.MYSQL) + void list() throws Exception { + // Initialize your Java lists + List<Integer> listA = List.of(1, 2, 3, 4, 5); + List<Integer> listB = new ArrayList<>(); + + // Set up Calcite schema + SchemaPlus rootSchema = Frameworks.createRootSchema(true); + rootSchema.add("MY_SCHEMA", new ListSchema(listA, listB)); + + // Create and add 'city' table + DataSchema cityRowType = new DataSchemaImpl("city", List.of( + new DataColumnFixed("id", Cardinality.OPTIONAL, Type.INTEGER), + new DataColumnFixed("name", Cardinality.OPTIONAL, Type.STRING), + new DataColumnFixed("geometry", Cardinality.OPTIONAL, Type.GEOMETRY))); + + DataTable cityDataTable = new BaremapsDataTable( + cityRowType, + new IndexedDataList<>(new AppendOnlyLog<>(new RowDataType(cityRowType)))); + + GeometryFactory geometryFactory = new GeometryFactory(); + cityDataTable.add(new DataRowImpl(cityDataTable.schema(), + List.of(1, "Paris", geometryFactory.createPoint(new Coordinate(2.3522, 48.8566))))); + cityDataTable.add(new DataRowImpl(cityDataTable.schema(), + List.of(2, "New York", geometryFactory.createPoint(new Coordinate(-74.0060, 40.7128))))); + + SqlDataTable citySqlDataTable = new SqlDataTable(cityDataTable); + rootSchema.add("CITY", citySqlDataTable); + + // Configure the framework + FrameworkConfig config = Frameworks.newConfigBuilder() + .defaultSchema(rootSchema.getSubSchema("MY_SCHEMA")) .build(); - // Create the parser from the config - SqlParser parser = SqlParser.create(sqlScript, config); + // Create a planner + Planner planner = Frameworks.getPlanner(config); + + // Define the SQL query to populate list_b from list_a + String sql = "SELECT V * 2 AS V FROM LIST_A"; + + // Parse the SQL query + org.apache.calcite.sql.SqlNode parsed = planner.parse(sql); - // Parse the script as a list of statements - SqlNodeList sqlNodeList = parser.parseStmtList(); + // Validate the SQL query + org.apache.calcite.sql.SqlNode validated = planner.validate(parsed); - // Iterate and print each parsed statement - for (SqlNode sqlNode : sqlNodeList) { - System.out.println("Parsed statement: " + sqlNode.toString()); + // Convert the SQL query to a relational expression + RelNode rel = planner.rel(validated).rel; + + Interpreter interpreter = new Interpreter(DataContexts.EMPTY, rel); + + // Create an interpreter to execute the RelNode + for (Object[] row : interpreter.asEnumerable()) { + listB.add((Integer) row[0]); } + + // Display the results + System.out.println("List A: " + listA); + System.out.println("List B (after SQL): " + listB); } }
