Hi, thank you so much for reviewing my question 🙇♂️ I thought maybe I was ignorant, and maybe there was a secret way to inject context using Contexts.of(Object...). Judging from your response this is not possible.
I am determined to solve this puzzle. As an alternative do you think it would be possible to parse a statement like this: SELECT * FROM emps JOIN depts ON emps.deptno = depts.deptno And then extract this portion JOIN depts ON emps.deptno = depts.deptno And add it on top of an existing relBuilder? Thank you so much for your help Kindest regards From, Hugh Pearse On Wed, 25 Jun 2025, 19:46 Mihai Budiu, <mbu...@gmail.com> wrote: > In general you pass to the validator a SQL query; the validator will make > sure the query is fine, and it will rewrite it to make it more explicit. > This entails for example resolving identifiers: what is "deptno" - a table, > a column, and if it's a column, what table does it belong to? > > For your expression with "free" variables the validator does not have > enough information to understand what these identifiers refer to. > > Even if the validator was enhanced to "understand" such expressions, the > validator cannot give them a "meaning". When you say "SELECT deptno FROM > emps", deptno implicitly iterates over all rows in the emps table, and the > meaning of this statement is to produce a table from all results produced > by iterating. > > What is the meaning of your expression? What would you expect the > validator to produce if it worked? > > Mihai > > ________________________________ > From: Hugh Pearse <hughpea...@gmail.com> > Sent: Wednesday, June 25, 2025 11:30 AM > To: dev@calcite.apache.org <dev@calcite.apache.org> > Subject: SqlParser.parseExpression() > > Hi team, > I am trying to join 2 tables, but want to provide the join condition (join > ON x=y) as a text input which is parsed. > > Example scenario: > > 1. user provides input: > emps.deptno = depts.deptno > 2. calcite parses join expression and creates join > > Expected result > SELECT * FROM emps JOIN depts ON emps.deptno = depts.deptno > > Actual result: > I am facing error: > Table 'emps' not found > at > > java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native > Method) > at > > java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77) > at > > java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) > at > > java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500) > at > java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481) > at > org.apache.calcite.runtime.Resources$ExInstWithCause.ex(Resources.java:507) > at org.apache.calcite.sql.SqlUtil.newContextException(SqlUtil.java:948) > at org.apache.calcite.sql.SqlUtil.newContextException(SqlUtil.java:933) > at > > org.apache.calcite.sql.validate.SqlValidatorImpl.newValidationError(SqlValidatorImpl.java:5643) > at > > org.apache.calcite.sql.validate.DelegatingScope.fullyQualify(DelegatingScope.java:364) > at > > org.apache.calcite.sql.validate.SqlValidatorImpl.validateIdentifier(SqlValidatorImpl.java:3348) > at > org.apache.calcite.sql.SqlIdentifier.validateExpr(SqlIdentifier.java:307) > at org.apache.calcite.sql.SqlOperator.validateCall(SqlOperator.java:475) > at > > org.apache.calcite.sql.validate.SqlValidatorImpl.validateCall(SqlValidatorImpl.java:6371) > at org.apache.calcite.sql.SqlCall.validate(SqlCall.java:143) > at > > org.apache.calcite.sql.validate.SqlValidatorImpl.validateScopedExpression(SqlValidatorImpl.java:1101) > at > > org.apache.calcite.sql.validate.SqlValidatorImpl.validate(SqlValidatorImpl.java:807) > > > Code: > > ```java > import com.google.common.collect.ImmutableList; > import org.apache.calcite.adapter.java.ReflectiveSchema; > import org.apache.calcite.config.Lex; > import org.apache.calcite.jdbc.CalciteConnection; > import org.apache.calcite.jdbc.CalciteSchema; > import org.apache.calcite.plan.RelOptCluster; > import org.apache.calcite.plan.ViewExpanders; > import org.apache.calcite.prepare.CalciteCatalogReader; > import org.apache.calcite.rel.type.RelDataTypeFactory; > import org.apache.calcite.rex.RexBuilder; > import org.apache.calcite.rex.RexNode; > import org.apache.calcite.schema.SchemaPlus; > import org.apache.calcite.sql.SqlNode; > import org.apache.calcite.sql.fun.SqlStdOperatorTable; > import org.apache.calcite.sql.parser.SqlParser; > import org.apache.calcite.sql.validate.SqlValidator; > import org.apache.calcite.sql.validate.SqlValidatorUtil; > import org.apache.calcite.sql2rel.SqlToRelConverter; > import org.apache.calcite.tools.FrameworkConfig; > import org.apache.calcite.tools.Frameworks; > import org.apache.calcite.tools.RelBuilder; > import org.junit.jupiter.api.Test; > > import java.sql.Connection; > import java.sql.DriverManager; > import java.util.Properties; > > public class JoinTest { > > public static class HrSchema { > public final Employee[] emps = { > new Employee(100, "Alice", 10), > new Employee(200, "Bob", 20) > }; > public final Department[] depts = { > new Department(10, "Sales"), > new Department(20, "Engineering") > }; > } > > public static class Employee { > public final int empid; > public final String name; > public final int deptno; > > public Employee(int empid, String name, int deptno) { > this.empid = empid; > this.name = name; > this.deptno = deptno; > } > } > > public static class Department { > public final int deptno; > public final String name; > > public Department(int deptno, String name) { > this.deptno = deptno; > this.name = name; > } > } > > @Test > public void testJoinToRexNode() throws Exception { > Properties props = new Properties(); > Connection connection = > DriverManager.getConnection("jdbc:calcite:", props); > CalciteConnection calciteConn = > connection.unwrap(CalciteConnection.class); > SchemaPlus rootSchema = calciteConn.getRootSchema(); > rootSchema.add("hr", new ReflectiveSchema(new HrSchema())); > calciteConn.setSchema("hr"); > > FrameworkConfig config = Frameworks.newConfigBuilder() > .parserConfig(SqlParser.config().withLex(Lex.MYSQL)) > .defaultSchema(rootSchema.getSubSchema("hr")) > .build(); > > String sql = "SELECT * FROM emps JOIN depts ON emps.deptno = > depts.deptno"; > > SqlValidator.Config sqlValidatorConfig = > config.getSqlValidatorConfig(); > SqlParser.Config parserConfig = config.getParserConfig(); > > ImmutableList<String> defaultSchemaPath = ImmutableList.of(); > RelBuilder relBuilder = RelBuilder.create(config); > RelOptCluster cluster = relBuilder.getCluster(); > RexBuilder rexBuilder = relBuilder.getRexBuilder(); > RelDataTypeFactory typeFactory = rexBuilder.getTypeFactory(); > CalciteSchema calciteSchema = > CalciteSchema.from(rootSchema.getSubSchema("hr")); > CalciteCatalogReader calciteCatalogReader = new > CalciteCatalogReader( > calciteSchema, > defaultSchemaPath, > typeFactory, > calciteConn.config() > ); > > SqlValidator sqlValidator = SqlValidatorUtil.newValidator( > SqlStdOperatorTable.instance(), > calciteCatalogReader, > typeFactory, > sqlValidatorConfig > ); > > SqlToRelConverter sqlToRelConverter = new SqlToRelConverter( > ViewExpanders.simpleContext(cluster), > sqlValidator, > calciteCatalogReader, > cluster, > config.getConvertletTable(), > config.getSqlToRelConverterConfig() > ); > > // First test (works) > SqlParser firstParser = SqlParser.create(sql, parserConfig); > SqlNode firstSqlNode = firstParser.parseQuery(); > SqlNode firstValidatedSqlNode = > sqlValidator.validate(firstSqlNode); > RexNode firstRexNode = > sqlToRelConverter.convertExpression(firstValidatedSqlNode); > System.out.println(firstRexNode); > > // Second test (fails) > sql = "emps.deptno = depts.deptno"; > SqlParser secondParser = SqlParser.create(sql, parserConfig); > SqlNode secondSqlNode = secondParser.parseExpression(); > SqlNode secondValidatedSqlNode = > sqlValidator.validate(secondSqlNode); > RexNode secondRexNode = > sqlToRelConverter.convertExpression(secondValidatedSqlNode); > } > } > ``` > > error is raised at this line: > SqlNode secondValidatedSqlNode = sqlValidator.validate(secondSqlNode); > > my questions are, > 1. is this type of expression even supported? > 2. its a bug with calcite or a bug with my code? > > From, > Hugh Pearse >