diff --git a/persistence-modules/java-calcite/pom.xml b/persistence-modules/java-calcite/pom.xml
new file mode 100644
index 0000000000..f0ab35f1b1
--- /dev/null
+++ b/persistence-modules/java-calcite/pom.xml
@@ -0,0 +1,45 @@
+
+
+ 4.0.0
+
+ org.example
+ java-calcite
+ 1.0-SNAPSHOT
+
+ com.baeldung
+ persistence-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 9
+
+
+
+
+
+
+
+ org.apache.calcite
+ calcite-core
+ ${calcite.version}
+
+
+ org.apache.calcite
+ calcite-file
+ ${calcite.version}
+
+
+
+
+ 1.34.0
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/java-calcite/src/main/java/com/baledung/calcite/model/CompanySchema.java b/persistence-modules/java-calcite/src/main/java/com/baledung/calcite/model/CompanySchema.java
new file mode 100644
index 0000000000..78b9cb243f
--- /dev/null
+++ b/persistence-modules/java-calcite/src/main/java/com/baledung/calcite/model/CompanySchema.java
@@ -0,0 +1,7 @@
+package com.baledung.calcite.model;
+
+public class CompanySchema {
+ public Employee[] employees;
+ public Department[] departments;
+
+}
diff --git a/persistence-modules/java-calcite/src/main/java/com/baledung/calcite/model/Department.java b/persistence-modules/java-calcite/src/main/java/com/baledung/calcite/model/Department.java
new file mode 100644
index 0000000000..eeb7552b00
--- /dev/null
+++ b/persistence-modules/java-calcite/src/main/java/com/baledung/calcite/model/Department.java
@@ -0,0 +1,11 @@
+package com.baledung.calcite.model;
+
+public class Department {
+ public String deptId;
+ public String deptName;
+
+ public Department(String deptId, String deptName) {
+ this.deptId = deptId;
+ this.deptName = deptName;
+ }
+}
diff --git a/persistence-modules/java-calcite/src/main/java/com/baledung/calcite/model/Employee.java b/persistence-modules/java-calcite/src/main/java/com/baledung/calcite/model/Employee.java
new file mode 100644
index 0000000000..6c8e499f0e
--- /dev/null
+++ b/persistence-modules/java-calcite/src/main/java/com/baledung/calcite/model/Employee.java
@@ -0,0 +1,14 @@
+package com.baledung.calcite.model;
+
+public class Employee {
+ public String name;
+ public String id;
+
+ public String deptId;
+
+ public Employee(String name, String id, String deptId) {
+ this.name = name;
+ this.id = id;
+ this.deptId = deptId;
+ }
+}
diff --git a/persistence-modules/java-calcite/src/main/resources/puml/calcite-adapter-cld.puml b/persistence-modules/java-calcite/src/main/resources/puml/calcite-adapter-cld.puml
new file mode 100644
index 0000000000..319cd14df2
--- /dev/null
+++ b/persistence-modules/java-calcite/src/main/resources/puml/calcite-adapter-cld.puml
@@ -0,0 +1,58 @@
+@startuml
+'https://plantuml.com/class-diagram
+
+
+skinparam Handwritten true
+skinparam ClassBorderColor black/#63b175
+skinparam BackgroundColor #fdf8f6
+skinparam class {
+ ArrowColor black/#63b175
+
+}
+
+'hide empty methods
+hide empty attributes
+
+
+interface Schema {
++getTable()
++getType()
++getFunctions()
++more methods()..
+}
+
+interface SchemaFactory {
++creates()
+}
+
+interface Table {
+
+}
+
+interface TableFactory {
+ +create()
+}
+
+interface SchemaFactory {
+}
+interface Schema {
+}
+interface Table {
+}
+interface TableFactory {
+}
+
+
+SchemaFactory -right-> Schema:creates
+CassandraSchemaFactory -right-|> SchemaFactory:implements
+CsvSchemaFactory -down-|> SchemaFactory:implements
+MongoSchemaFactory -down-|> SchemaFactory:implements
+FileSchemaFactory -down-|> SchemaFactory:implements
+TableFactory -right-> Table:creates
+Table <-up- Schema:gets
+CassandraSchema -down-|> Schema:implements
+CsvSchema -down-|> Schema:implements
+MongoSchema -up-|> Schema:implements
+SplunkSchema -up-|> Schema:implements
+
+@enduml
\ No newline at end of file
diff --git a/persistence-modules/java-calcite/src/test/java/com/baeldung/calcite/CalciteUnitTest.java b/persistence-modules/java-calcite/src/test/java/com/baeldung/calcite/CalciteUnitTest.java
new file mode 100644
index 0000000000..ffb8ee1cc2
--- /dev/null
+++ b/persistence-modules/java-calcite/src/test/java/com/baeldung/calcite/CalciteUnitTest.java
@@ -0,0 +1,97 @@
+package com.baeldung.calcite;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.calcite.adapter.java.ReflectiveSchema;
+import org.apache.calcite.jdbc.CalciteConnection;
+import org.apache.calcite.schema.Schema;
+import org.apache.calcite.schema.SchemaPlus;
+import static org.junit.jupiter.api.Assertions.*;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.baledung.calcite.model.CompanySchema;
+import com.baledung.calcite.model.Department;
+import com.baledung.calcite.model.Employee;
+
+public class CalciteUnitTest {
+ Logger logger = LoggerFactory.getLogger(CalciteUnitTest.class);
+ static CompanySchema companySchema = new CompanySchema();
+
+ @Test
+ void whenCsvSchema_thenQuerySuccess() throws SQLException {
+ Properties info = new Properties();
+ info.put("model", getPath("model.json"));
+ try(Connection connection = DriverManager.getConnection("jdbc:calcite:", info)) {
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("select * from trades.trade");
+
+ assertEquals(3, resultSet.getMetaData().getColumnCount());
+
+ List tradeIds = new ArrayList<>();
+ while(resultSet.next()) {
+ tradeIds.add(resultSet.getInt("tradeid"));
+ }
+
+ assertEquals(3, tradeIds.size());
+ }
+ }
+
+ private String getPath(String model) {
+ URL url = ClassLoader.getSystemClassLoader().getResource(model);
+ logger.info("path fetched :" + url.getPath());
+ return url.getPath();
+ }
+
+ @BeforeAll
+ static void setup() {
+ Department dept1 = new Department("HR", "Human Resource");
+ Department dept2 = new Department("MKT", "Marketing");
+ Department dept3 = new Department("FIN", "Finance");
+
+ Employee emp1 = new Employee("Tom", "1234", "HR");
+ Employee emp2 = new Employee("Harry", "39731", "FIN");
+ Employee emp3 = new Employee("Danny", "45632", "FIN");
+ Employee emp4 = new Employee("Jenny", "78654", "MKT");
+
+ companySchema.departments = new Department[]{dept1, dept2, dept3};
+ companySchema.employees = new Employee[]{emp1, emp2, emp3, emp4};
+ }
+
+ @Test
+ void whenQueryEmployeesObject_thenQuerySuccess() throws SQLException {
+ Properties info = new Properties();
+ info.setProperty("lex", "JAVA");
+ Connection connection = DriverManager.getConnection("jdbc:calcite:", info);
+ CalciteConnection calciteConnection = connection.unwrap(CalciteConnection.class);
+ SchemaPlus rootSchema = calciteConnection.getRootSchema();
+ Schema schema = new ReflectiveSchema(companySchema);
+ rootSchema.add("company", schema);
+ Statement statement = calciteConnection.createStatement();
+ String query = "select dept.deptName, count(emp.id) "
+ + "from company.employees as emp "
+ + "join company.departments as dept "
+ + "on (emp.deptId = dept.deptId) "
+ + "group by dept.deptName";
+
+ assertDoesNotThrow(() -> {
+ ResultSet resultSet = statement.executeQuery(query);
+ while (resultSet.next()) {
+ logger.info("Dept Name:" + resultSet.getString(1)
+ + " No. of employees:" + resultSet.getInt(2));
+ }
+ });
+ }
+}
diff --git a/persistence-modules/java-calcite/src/test/resources/model.json b/persistence-modules/java-calcite/src/test/resources/model.json
new file mode 100644
index 0000000000..59202abf05
--- /dev/null
+++ b/persistence-modules/java-calcite/src/test/resources/model.json
@@ -0,0 +1,14 @@
+{
+ "version": "1.0",
+ "defaultSchema": "TRADES",
+ "schemas": [
+ {
+ "name": "TRADES",
+ "type": "custom",
+ "factory": "org.apache.calcite.adapter.file.FileSchemaFactory",
+ "operand": {
+ "directory": "trades"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/persistence-modules/java-calcite/src/test/resources/trades/TRADE.csv b/persistence-modules/java-calcite/src/test/resources/trades/TRADE.csv
new file mode 100644
index 0000000000..6ec7f1cfa9
--- /dev/null
+++ b/persistence-modules/java-calcite/src/test/resources/trades/TRADE.csv
@@ -0,0 +1,4 @@
+tradeid:int,productid:string,qty:int
+232312123,"RFTXC",100
+232312124,"RFUXC",200
+232312125,"RFSXC",1000
\ No newline at end of file
diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml
index 7634e5ba91..5ca2ffbf1a 100644
--- a/persistence-modules/pom.xml
+++ b/persistence-modules/pom.xml
@@ -38,6 +38,7 @@
hibernate-queries
hibernate-enterprise
influxdb
+ java-calcite
java-cassandra
java-cockroachdb
java-jdbi