方法
org.apache.calcite.tools.RelBuilder#field
核心方法
org.apache.calcite.tools.RelBuilder#field(int inputCount, int inputOrdinal, int fieldOrdinal,boolean alias)
inputCount:当前数据源(输入的表)的数量
inputOrdinal:在当前上下文中数据源的下标
fieldOrdinal:在当前上下文中字段的下标
alias:是否别名
讲解
元数据
testdb.travelrecord(id,user_id,traveldate,fee,days,blob,d) 7个字段
testdb.address(id,address) 2个字段
RelBuilder relBuilder = RelBuilder.create(config);
RelNode table = relBuilder
.scan("testdb","travelrecord")
.scan("testdb","address")
.join(JoinRelType.INNER, relBuilder.equals(relBuilder.field(2,0,0),relBuilder.field(2,1,1)))
.filter(relBuilder.and(relBuilder.equals(relBuilder.field(1,0,"id"),relBuilder.literal(1))))
.project(relBuilder.field(1,0,0), relBuilder.field(1,0,1))
.build();
join(JoinRelType.INNER, relBuilder.equals(relBuilder.field(2,0,0),relBuilder.field(2,1,8)))
2是当前的数据源数量,即testdb.travelrecord和testdb.address两个
relBuilder.field(2,0,0)中的第一个0是testdb.travelrecord所在的下标
relBuilder.field(2,1,1)中的1是testdb.address所在的下标
在join之后,字段按照数据源的顺序在栈顶依次排开
alias:是否别名,此参数一般为false
如果为true,同时指向的字段名与数据源字段不符,则建立别名字段
否则,直接指向数据源的输入值
以此封装得到下面的方法
public RexInputRef field(int inputCount, int inputOrdinal, int fieldOrdinal) //alias = false
public RexInputRef field(int fieldOrdinal)//inputCount = 1,inputOrdinal = 0
public RexInputRef field(int inputCount, int inputOrdinal, String fieldName)//根据上下文查找字段的下标
public RexInputRef field(String fieldName)//inputCount = 1,inputOrdinal = 0
public RexNode field(int inputCount, String alias, String fieldName) //引用别名和目标数据源字段名都相同的字段
public RexNode field(String alias, String fieldName)//inputCount = 1
错误例子
RelBuilder relBuilder = RelBuilder.create(config);
RelNode table = relBuilder
.scan("testdb","travelrecord")
.as("t")
.scan("testdb","address")
.as("a")
.join(JoinRelType.INNER, relBuilder.equals(relBuilder.field("t","id"),
relBuilder.field("a","id")))
.filter(relBuilder.and(relBuilder.equals(relBuilder.field(1,0,"id"),relBuilder.literal(1))))
.project(relBuilder.field(1,0,"id"), relBuilder.field(1,0,"user_id"))
.build();
java.lang.IllegalArgumentException: no aliased field found; fields are: [\{aliases=[address, a],fieldName=id}, \{aliases=[address, a],fieldName=addressname}]java.lang.IllegalArgumentException: no aliased field found; fields are: [\{aliases=[address, a],fieldName=id}, \{aliases=[address, a],fieldName=addressname}] at org.apache.calcite.tools.RelBuilder.field(RelBuilder.java:511) at org.apache.calcite.tools.RelBuilder.field(RelBuilder.java:487)
无法根据上下文找到t.id,因为t不在栈顶,在栈顶的是a,此时把relBuilder.field("t","id")改为relBuilder.field(2,"t","id")即可
RelBuilder是使用栈来构建树,字段查找需要数据源在栈的位置和范围的信息,而relBuilder.field("t","id")假定了数据源只有一个的情况,也就是栈顶部第一个位置——栈顶。而
.scan("testdb","travelrecord")
.as("t")
.scan("testdb","address")
.as("a")
使t位于栈顶部第二个位置,所以relBuilder无法找到t。