-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Query planner passes: AST->logical, logical->resolved, resolved->phys…
…ical Not yet integrated with anything.
- Loading branch information
Showing
17 changed files
with
1,836 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package org.partiql.lang.planner | ||
|
||
import org.partiql.lang.eval.BindingCase | ||
import org.partiql.lang.eval.BindingName | ||
|
||
/** Indicates the result of an attempt to resolve a global binding. */ | ||
sealed class ResolutionResult { | ||
/** | ||
* A success case, indicates the [uniqueId] of the match to the [BindingName] in the global scope. | ||
* Typically, this is defined by the storage layer. | ||
*/ | ||
data class GlobalVariable(val uniqueId: String) : ResolutionResult() | ||
|
||
/** | ||
* A success case, indicates the [index] of the only possible match to the [BindingName] in a local lexical scope. | ||
* This is `internal` because [index] is an implementation detail that shouldn't be accessible outside of this | ||
* library. | ||
*/ | ||
internal data class LocalVariable(val index: Int) : ResolutionResult() | ||
|
||
/** A failure case, indicates that resolution did not match any variable. */ | ||
object Undefined : ResolutionResult() | ||
} | ||
|
||
fun interface GlobalBindings { | ||
/** | ||
* Implementations try to resolve a global variable which is typically a database table, as identified by a | ||
* [bindingName]. The [bindingName] includes both the name as specified by the query author and a [BindingCase] | ||
* which indicates if query author included double quotes (") which mean the lookup should be case-sensitive. | ||
* | ||
* Implementations of this function must return: | ||
* | ||
* - [ResolutionResult.GlobalVariable] if [bindingName] matches a global variable (typically a database table). | ||
* - [ResolutionResult.Undefined] if no identifier matches [bindingName]. | ||
* | ||
* When determining if a variable name matches a global variable, it is important to consider if the comparison | ||
* should be case-sensitive or case-insensitive. @see [BindingName.bindingCase]. In the event that more than one | ||
* variable matches a case-insensitive [BindingName], the implementation must still select one of them | ||
* without providing an error. (This is consistent with Postres's behavior in this scenario.) | ||
* | ||
* Note that while [ResolutionResult.LocalVariable] exists, it is intentionally marked `internal` and cannot | ||
* be used by outside of this project.. | ||
*/ | ||
fun resolve(bindingName: BindingName): ResolutionResult | ||
} | ||
|
||
private val EMPTY = GlobalBindings { ResolutionResult.Undefined } | ||
|
||
/** Convenience function for obtaining an instance of [GlobalBindings] with no defined variables. */ | ||
fun emptyGlobalBindings(): GlobalBindings = EMPTY |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package org.partiql.lang.planner | ||
import org.partiql.lang.errors.Problem | ||
|
||
sealed class PassResult<TResult> { | ||
/** | ||
* Indicates query planning was successful and includes a list of any warnings that were encountered along the way. | ||
*/ | ||
data class Success<TResult>(val result: TResult, val warnings: List<Problem>) : PassResult<TResult>() | ||
|
||
/** | ||
* Indicates query planning was not successful and includes a list of errors and warnings that were encountered | ||
* along the way. | ||
*/ | ||
data class Error<TResult>(val errors: List<Problem>) : PassResult<TResult>() | ||
} |
25 changes: 25 additions & 0 deletions
25
lang/src/org/partiql/lang/planner/transforms/AstNormalize.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package org.partiql.lang.planner.transforms | ||
|
||
import org.partiql.lang.domains.PartiqlAst | ||
import org.partiql.lang.eval.visitors.FromSourceAliasVisitorTransform | ||
import org.partiql.lang.eval.visitors.PipelinedVisitorTransform | ||
import org.partiql.lang.eval.visitors.SelectListItemAliasVisitorTransform | ||
import org.partiql.lang.eval.visitors.SelectStarVisitorTransform | ||
|
||
/** | ||
* Executes the [SelectListItemAliasVisitorTransform], [FromSourceAliasVisitorTransform] and | ||
* [SelectStarVisitorTransform] passes on the receiver. | ||
*/ | ||
fun PartiqlAst.Statement.normalize(): PartiqlAst.Statement { | ||
// Since these passes all work on PartiqlAst, we can use a PipelinedVisitorTransform which executes each | ||
// specified VisitorTransform in sequence. | ||
val transforms = PipelinedVisitorTransform( | ||
// Synthesizes unspecified `SELECT <expr> AS ...` aliases | ||
SelectListItemAliasVisitorTransform(), | ||
// Synthesizes unspecified `FROM <expr> AS ...` aliases | ||
FromSourceAliasVisitorTransform(), | ||
// Changes `SELECT * FROM a, b` to SELECT a.*, b.* FROM a, b` | ||
SelectStarVisitorTransform() | ||
) | ||
return transforms.transformStatement(this) | ||
} |
Oops, something went wrong.