Implement SPLIT keyword in SELECT statement
This commit is contained in:
parent
261aff0ee2
commit
971302ecf5
5 changed files with 74 additions and 1 deletions
|
@ -54,6 +54,7 @@ type iterator struct {
|
||||||
expr sql.Fields
|
expr sql.Fields
|
||||||
what sql.Exprs
|
what sql.Exprs
|
||||||
cond sql.Expr
|
cond sql.Expr
|
||||||
|
split sql.Idents
|
||||||
group sql.Groups
|
group sql.Groups
|
||||||
order sql.Orders
|
order sql.Orders
|
||||||
limit int
|
limit int
|
||||||
|
@ -133,6 +134,7 @@ func (i *iterator) Close() {
|
||||||
i.expr = nil
|
i.expr = nil
|
||||||
i.what = nil
|
i.what = nil
|
||||||
i.cond = nil
|
i.cond = nil
|
||||||
|
i.split = nil
|
||||||
i.group = nil
|
i.group = nil
|
||||||
i.order = nil
|
i.order = nil
|
||||||
i.limit = -1
|
i.limit = -1
|
||||||
|
@ -149,8 +151,10 @@ func (i *iterator) setupState(ctx context.Context) {
|
||||||
i.expr = nil
|
i.expr = nil
|
||||||
i.what = nil
|
i.what = nil
|
||||||
i.cond = nil
|
i.cond = nil
|
||||||
|
i.split = nil
|
||||||
i.group = nil
|
i.group = nil
|
||||||
i.order = nil
|
i.order = nil
|
||||||
|
i.split = nil
|
||||||
i.limit = -1
|
i.limit = -1
|
||||||
i.start = -1
|
i.start = -1
|
||||||
i.versn = math.MaxInt64
|
i.versn = math.MaxInt64
|
||||||
|
@ -160,6 +164,7 @@ func (i *iterator) setupState(ctx context.Context) {
|
||||||
i.expr = stm.Expr
|
i.expr = stm.Expr
|
||||||
i.what = stm.What
|
i.what = stm.What
|
||||||
i.cond = stm.Cond
|
i.cond = stm.Cond
|
||||||
|
i.split = stm.Split
|
||||||
i.group = stm.Group
|
i.group = stm.Group
|
||||||
i.order = stm.Order
|
i.order = stm.Order
|
||||||
i.tasks = stm.Parallel
|
i.tasks = stm.Parallel
|
||||||
|
@ -865,6 +870,10 @@ func (i *iterator) Yield(ctx context.Context) (out []interface{}, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(i.split) > 0 {
|
||||||
|
i.res = i.Split(ctx, i.res)
|
||||||
|
}
|
||||||
|
|
||||||
if len(i.group) > 0 {
|
if len(i.group) > 0 {
|
||||||
i.res = i.Group(ctx, i.res)
|
i.res = i.Group(ctx, i.res)
|
||||||
}
|
}
|
||||||
|
@ -887,6 +896,42 @@ func (i *iterator) Yield(ctx context.Context) (out []interface{}, err error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *iterator) Split(ctx context.Context, arr []interface{}) (out []interface{}) {
|
||||||
|
|
||||||
|
for _, s := range i.split {
|
||||||
|
|
||||||
|
out = make([]interface{}, 0)
|
||||||
|
|
||||||
|
for _, a := range arr {
|
||||||
|
|
||||||
|
doc := data.Consume(a)
|
||||||
|
|
||||||
|
pth := make([]string, 0)
|
||||||
|
|
||||||
|
switch doc.Get(s.VA).Data().(type) {
|
||||||
|
case []interface{}:
|
||||||
|
pth = append(pth, s.VA, "*")
|
||||||
|
default:
|
||||||
|
pth = append(pth, s.VA)
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.Walk(func(key string, val interface{}, exi bool) error {
|
||||||
|
doc := doc.Copy()
|
||||||
|
doc.Set(val, s.VA)
|
||||||
|
out = append(out, doc.Data())
|
||||||
|
return nil
|
||||||
|
}, pth...)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
arr = out
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (i *iterator) Group(ctx context.Context, arr []interface{}) (out []interface{}) {
|
func (i *iterator) Group(ctx context.Context, arr []interface{}) (out []interface{}) {
|
||||||
|
|
||||||
var grp []*groupable
|
var grp []*groupable
|
||||||
|
|
|
@ -170,6 +170,7 @@ type SelectStatement struct {
|
||||||
Expr Fields
|
Expr Fields
|
||||||
What Exprs
|
What Exprs
|
||||||
Cond Expr
|
Cond Expr
|
||||||
|
Split Idents
|
||||||
Group Groups
|
Group Groups
|
||||||
Order Orders
|
Order Orders
|
||||||
Limit Expr
|
Limit Expr
|
||||||
|
|
|
@ -39,6 +39,10 @@ func (p *parser) parseSelectStatement() (stmt *SelectStatement, err error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if stmt.Split, err = p.parseSplit(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if stmt.Group, err = p.parseGroup(); err != nil {
|
if stmt.Group, err = p.parseGroup(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -142,6 +146,26 @@ func (p *parser) parseFields() (mul Fields, err error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *parser) parseSplit() (Idents, error) {
|
||||||
|
|
||||||
|
// The next token that we expect to see is a
|
||||||
|
// SPLIT token, and if we don't find one then
|
||||||
|
// return nil, with no error.
|
||||||
|
|
||||||
|
if _, _, exi := p.mightBe(SPLIT); !exi {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't need to have a ON token, but we
|
||||||
|
// allow it so that the SQL query would read
|
||||||
|
// better when compared to english.
|
||||||
|
|
||||||
|
_, _, _ = p.mightBe(ON)
|
||||||
|
|
||||||
|
return p.parseIdioms()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (p *parser) parseGroup() (mul Groups, err error) {
|
func (p *parser) parseGroup() (mul Groups, err error) {
|
||||||
|
|
||||||
// The next token that we expect to see is a
|
// The next token that we expect to see is a
|
||||||
|
|
|
@ -225,10 +225,11 @@ func (this KillStatement) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this SelectStatement) String() string {
|
func (this SelectStatement) String() string {
|
||||||
return print("SELECT %v FROM %v%v%v%v%v%v%v%v%v",
|
return print("SELECT %v FROM %v%v%v%v%v%v%v%v%v%v",
|
||||||
this.Expr,
|
this.Expr,
|
||||||
this.What,
|
this.What,
|
||||||
maybe(this.Cond != nil, print(" WHERE %v", this.Cond)),
|
maybe(this.Cond != nil, print(" WHERE %v", this.Cond)),
|
||||||
|
maybe(this.Split != nil, print(" SPLIT %v", this.Split)),
|
||||||
this.Group,
|
this.Group,
|
||||||
this.Order,
|
this.Order,
|
||||||
maybe(this.Limit != nil, print(" LIMIT %v", this.Limit)),
|
maybe(this.Limit != nil, print(" LIMIT %v", this.Limit)),
|
||||||
|
|
|
@ -183,6 +183,7 @@ const (
|
||||||
SIGNIN
|
SIGNIN
|
||||||
SIGNUP
|
SIGNUP
|
||||||
SOMECONTAINEDIN
|
SOMECONTAINEDIN
|
||||||
|
SPLIT
|
||||||
START
|
START
|
||||||
TABLE
|
TABLE
|
||||||
THEN
|
THEN
|
||||||
|
@ -360,6 +361,7 @@ var tokens = [...]string{
|
||||||
SIGNIN: "SIGNIN",
|
SIGNIN: "SIGNIN",
|
||||||
SIGNUP: "SIGNUP",
|
SIGNUP: "SIGNUP",
|
||||||
SOMECONTAINEDIN: "SOMECONTAINEDIN",
|
SOMECONTAINEDIN: "SOMECONTAINEDIN",
|
||||||
|
SPLIT: "SPLIT",
|
||||||
START: "START",
|
START: "START",
|
||||||
TABLE: "TABLE",
|
TABLE: "TABLE",
|
||||||
THEN: "THEN",
|
THEN: "THEN",
|
||||||
|
|
Loading…
Reference in a new issue