mirror of
https://github.com/pgsty/minio.git
synced 2026-08-09 07:43:29 +03:00
Add new SQL parser to support S3 Select syntax (#7102)
- New parser written from scratch, allows easier and complete parsing of the full S3 Select SQL syntax. Parser definition is directly provided by the AST defined for the SQL grammar. - Bring support to parse and interpret SQL involving JSON path expressions; evaluation of JSON path expressions will be subsequently added. - Bring automatic type inference and conversion for untyped values (e.g. CSV data).
This commit is contained in:
committed by
Harshavardhana
parent
0a28c28a8c
commit
2786055df4
+123
@@ -0,0 +1,123 @@
|
||||
package participle
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/alecthomas/participle/lexer"
|
||||
)
|
||||
|
||||
type contextFieldSet struct {
|
||||
pos lexer.Position
|
||||
strct reflect.Value
|
||||
field structLexerField
|
||||
fieldValue []reflect.Value
|
||||
}
|
||||
|
||||
// Context for a single parse.
|
||||
type parseContext struct {
|
||||
*rewinder
|
||||
lookahead int
|
||||
caseInsensitive map[rune]bool
|
||||
apply []*contextFieldSet
|
||||
}
|
||||
|
||||
func newParseContext(lex lexer.Lexer, lookahead int, caseInsensitive map[rune]bool) (*parseContext, error) {
|
||||
rew, err := newRewinder(lex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &parseContext{
|
||||
rewinder: rew,
|
||||
caseInsensitive: caseInsensitive,
|
||||
lookahead: lookahead,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Defer adds a function to be applied once a branch has been picked.
|
||||
func (p *parseContext) Defer(pos lexer.Position, strct reflect.Value, field structLexerField, fieldValue []reflect.Value) {
|
||||
p.apply = append(p.apply, &contextFieldSet{pos, strct, field, fieldValue})
|
||||
}
|
||||
|
||||
// Apply deferred functions.
|
||||
func (p *parseContext) Apply() error {
|
||||
for _, apply := range p.apply {
|
||||
if err := setField(apply.pos, apply.strct, apply.field, apply.fieldValue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
p.apply = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// Branch accepts the branch as the correct branch.
|
||||
func (p *parseContext) Accept(branch *parseContext) {
|
||||
p.apply = append(p.apply, branch.apply...)
|
||||
p.rewinder = branch.rewinder
|
||||
}
|
||||
|
||||
// Branch starts a new lookahead branch.
|
||||
func (p *parseContext) Branch() *parseContext {
|
||||
branch := &parseContext{}
|
||||
*branch = *p
|
||||
branch.apply = nil
|
||||
branch.rewinder = p.rewinder.Lookahead()
|
||||
return branch
|
||||
}
|
||||
|
||||
// Stop returns true if parsing should terminate after the given "branch" failed to match.
|
||||
func (p *parseContext) Stop(branch *parseContext) bool {
|
||||
if branch.cursor > p.cursor+p.lookahead {
|
||||
p.Accept(branch)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type rewinder struct {
|
||||
cursor, limit int
|
||||
tokens []lexer.Token
|
||||
}
|
||||
|
||||
func newRewinder(lex lexer.Lexer) (*rewinder, error) {
|
||||
r := &rewinder{}
|
||||
for {
|
||||
t, err := lex.Next()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if t.EOF() {
|
||||
break
|
||||
}
|
||||
r.tokens = append(r.tokens, t)
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (r *rewinder) Next() (lexer.Token, error) {
|
||||
if r.cursor >= len(r.tokens) {
|
||||
return lexer.EOFToken(lexer.Position{}), nil
|
||||
}
|
||||
r.cursor++
|
||||
return r.tokens[r.cursor-1], nil
|
||||
}
|
||||
|
||||
func (r *rewinder) Peek(n int) (lexer.Token, error) {
|
||||
i := r.cursor + n
|
||||
if i >= len(r.tokens) {
|
||||
return lexer.EOFToken(lexer.Position{}), nil
|
||||
}
|
||||
return r.tokens[i], nil
|
||||
}
|
||||
|
||||
// Lookahead returns a new rewinder usable for lookahead.
|
||||
func (r *rewinder) Lookahead() *rewinder {
|
||||
clone := &rewinder{}
|
||||
*clone = *r
|
||||
clone.limit = clone.cursor
|
||||
return clone
|
||||
}
|
||||
|
||||
// Keep this lookahead rewinder.
|
||||
func (r *rewinder) Keep() {
|
||||
r.limit = 0
|
||||
}
|
||||
Reference in New Issue
Block a user