forked from apache/druid
-
Notifications
You must be signed in to change notification settings - Fork 0
Calcite Table Functions
Paul Rogers edited this page Nov 9, 2022
·
4 revisions
-
MSQSqlModule
provides a binding toExternalOperatorConversion
:
SqlBindings.addOperatorConversion(binder, ExternalOperatorConversion.class);
-
ExternalOperator
is created via Guice. It is not registered in Guice, it is just created as needed, which is... -
ExternalOperatorConversion
is created via Guice, passing in theExternalOperator
instance. -
ExternalOperatorConversion
holds an instance ofSqlOperator
, specificallySqlUserDefinedTableMacro
, which is created via theExternalOperatorConversion
(called from Guice). - In this case, the Druid-specific class is
ExternalOperator
, which extendsSqlUserDefinedTableMacro
. - The
ExternalOperator
constructor causes the parameters to be created so they can be passed to the super constructor. - The
ExternalOperator
macro is given theExternalTableMacro
instance, and callsExternalTableMacro.getParameters()
to get the list of parameters.
Relationships:
CalcitePlannerModule MSQSqlModule
| |
Guice Guice Guice
| | |
DruidOperatorTable o-- ExternalOperatorConversion o-- ExternalOperator o-- ExternalTableMacro
| | |
v v v
SqlOperatorConversion SqlUserDefinedTableMacro TableMacro
|
v
SqlFunction
This means:
-
ExternalOperatorConversion
are statically defined, via Guice. - Each
ExternalOperatorConversion
holds onto the Calcite operator, in this case,ExternalOperator extends SqlUserDefinedTableMacro
. - So,
ExternalOperator
is also a singleton, created at startup. -
ExternalOperator
is an operator definition, which holds onto aExternalTableMacro
, which is also a definition, in itstableMacro
field. - The
ExternalTableMacro
parameters are created once, via the Guice-created instance.
It is not clear why ExternalTableMacro
is created via Guice, other than for completeness. It is only ever used by ExternalOperatorConversion
and probably could have been created directly within the constructor.
-
BaseDruidSqlValidator extends SqlValidatorImpl
validateNamespace(.)
calls -
ProcedureNamespace.validateImpl(.)
which special casesSqlUserDefinedTableMacro
- The special case calls
udf.getTable(.)
whereudf
is theExternalOperator extends SqlUserDefinedTableMacro
instance. -
getTable(.)
retrieves theTableMacro tableMacro
instance, in this case,ExternalTableMacro
. -
SqlUserDefinedTableMacro.getTable(.)
callsconvertArguments(.)
-
convertArguments()
callsExternalTableMacro extends TableMacro
getParameters()
(which creates another instance of the parameters.) -
SqlUserDefinedTableMacro.getTable()
then callsExternalOperator extends SqlUserDefinedTableMacro
apply(.)
to apply the arguments. - The arguments are given as a list of Java objects which match up to the parameters by position. The values are coerced to Java types using the
TypeFactory
associated with the planner. -
ExternalTableMacro.apply()
grabs the threeString
arguments, converts the value to JSON, and returns an instance ofExternalTable
that has anExternalDataSource
that holds the converted arguments. - The
ExternalTable
then becomes the "real" table referenced in theFROM
clause. -
ProcedureNamespace.validateImpl(.)
then callsExternalTable extends TranslatableTable
getRowType()
to get the row signature.
Basic structure:
Validator
|
| (calls)
|
ProcedureNamespace
|
| (is given instance of)
|
RelDataType o-- SqlUserDefinedTableMacro o-- TableMacro
| |
| | (creates)
| |
ProcedureNamespace ExternalTable o-- ExternalDataSource
Notes:
- It would seem that we can create the
ExternalTableMacro
parameters once, and reuse them: no need to create them over and over.
- SqlResourceCollectorShuttle
calls gets the
SqlOperatorfrom the
SqlCall` node when walking the tree. - The
SqlCall.getOperator()
method returns the associated operator, hereExternalOperator
. - After casting to
AuthorizableOperator
, the shuttle callsExternalOperator.computeResources(.)
to return the resource, which isEXTERNAL_RESOURCE_ACTION
.
-
SqlToRelConverter.convertCollectionTable(.)
call obtains theSqlOperator
from `SqlCall.getOperator(). - The operator here is
ExternalOperatorConversion extends SqlOperatorConversion
. -
convertCollectionTable(.)
special-casesSqlUserDefinedTableMacro
and again callsgetTable()
. -
getTable()
repeats the process above: again creating the parameters and again creating an instance ofExternalTable
. -
convertCollectionTable(.)
callsRelOptTableImpl.toRel(.)
which callsExternalTable.toRel(.)
. -
ExternalTable.toRel(.)
creates anExternalTableScan
instance to represent the scan. -
ExternalTableScan.deriveRowType()
again callsExternalTable.getRowType()
to convert the row type.
Questions:
- Can the row type be cached in
ExternalTable
to avoid multiple converstions? - Can the
ExternalTable
be cached to avoid multiple conversions?
(Something happened after the above.)