I don’t want to encourage people to subclass RelBuilder. It is not designed to be extended by subclassing.
Having said that, it seems reasonable to provide a way to find the table aliases. In https://issues.apache.org/jira/browse/CALCITE-4946 I added the method RelBuilder.size(); I was surprised that it was necessary, but it made a few things easier. A method that returns an immutable list of the N table aliases of the N stack entries would seem to complement size(). Julian > On Jun 20, 2024, at 3:40 PM, Ian Bertolacci > <[email protected]> wrote: > > Hello, > We have a class which extends RelBuilder to add some extra functionality, but > we are having issues with aliases being erased when popping the builder > stack, and there isn’t much recourse since the Frame stack is all private. > > For example, this is valid: > ``` > relBuilder.scan("T101").empty().field(1, "T101", "C0_7009") > ``` > Because the `RelBuilder.empty` implementation copies the alias in the Frame > from the top of the Frame stack before the `empty` call, and uses it as the > name in the frame created *by* the `empty` call. > > But people extending RelBuilder (us) cannot access or modify those private > members. > So we have no way to replace the node at the top of the stack without > eliminating the alias, and making referencing that alias illegal. > > For example, lets say we overrode the `empty()` method do effectively replace > the node that would be created by the base `empty()` implementation > ``` > @Override > public RelBuilder empty(){ > super.empty(); > // pop result from stack to maintain proper stack arrangement > RelNode oldEmptyNode = this.build(); > // and make new node > RelNode newEmptyNode = createNewEmptyNode( oldEmptyNode ); > // push new node on the stack > this.push(newEmptyNode); > } > ``` > By popping the stack, we erase the alias information, so calling `field` with > an alias after `empty`throws an exception, since after the empty call > (specifically the `build` call) the alias in the Frame no longer exists. > > The only solution to this would be to call `.as` immediately after the `push` > call to restore the alias: > ``` > @Override > public RelBuilder empty(){ > super.empty(); > // get the current alias > String currentAlias = ???; > // pop result from stack to maintain proper stack arrangement > RelNode oldEmptyNode = this.build(); > // and make new node > RelNode newEmptyNode = createNewEmptyNode( oldEmptyNode ); > // push new node on the stack > this.push(newEmptyNode); > // re-use the alias that existed before popping the node > this.alias(currentAlias); > } > ``` > But there doesn’t seem to be an existing way to ask what the *current* alias > is, so that it can be used in the `.as` call. > As it stands, it appears that it is not possible to add extension to > RelBuilder which either (a) cannot rely on an existing method to set-up the > Frame or (b) would cause the frame to be popped. > > Is that correct? Or is there actually a way to see what the top Frame’s alias > is without modifying the core RelBuilder code? > Thanks! > -Ian Bertolacci
