Now there are 2 ways to convert a RelOptTable to LogicalTableScan:
1. One way is to open the Config#isConvertTableAccess flag and the SqlToRelConverter would invoke the #toRel method which transforms the table to a node returned by the user(Usually a table scan).
2. Another way is to use the LogicalTableScan rule, this rule would invoke RelOptTable#toRel and wrap the returned node with a LogicalTableScan.
The difference between 1 and 2 is that, 2 happens in the planning rule but 1 happens in sql-to-rel conversion, 1 also supports to expand the table columns based on the defined default values expressions, see InitializerExpressionFactory#newColumnDefaultValue.
The problem with the InitializerExpressionFactory#newColumnDefaultValue is that it uses InitializerContext#convertExpression to convert a SqlNode, but if the SqlNode is not validated, we always got a RexCall with SqlUnresolvedFunction. We should give the user chance to validate their SqlNode or even we can support pure string expressions which can be used to persist.
Another problem with #toRel is that after the expressions applied as a projection, user has no chance to apply any other relational nodes if they want, we can actually support this, the same way as we support the column expressions.