fix: update allow list parser to support fragments
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
package qcode
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash/maphash"
|
||||
@ -329,6 +330,8 @@ func (p *Parser) parseFields(fields []Field) ([]Field, error) {
|
||||
return nil, fmt.Errorf("unexpected token: %s", p.peekNext())
|
||||
}
|
||||
|
||||
// fm := make(map[uint64]struct{})
|
||||
|
||||
for {
|
||||
if p.peek(itemEOF) {
|
||||
p.ignore()
|
||||
@ -385,6 +388,20 @@ func (p *Parser) parseFields(fields []Field) ([]Field, error) {
|
||||
f := &fields[i]
|
||||
f.ID = int32(i)
|
||||
|
||||
// var name string
|
||||
|
||||
// if f.Alias != "" {
|
||||
// name = f.Alias
|
||||
// } else {
|
||||
// name = f.Name
|
||||
// }
|
||||
|
||||
// if _, ok := fm[name]; ok {
|
||||
// continue
|
||||
// } else {
|
||||
// fm[name] = struct{}{}
|
||||
// }
|
||||
|
||||
// If this is the top-level point the parent to the parent of the
|
||||
// previous field.
|
||||
if f.ParentID == -1 {
|
||||
@ -416,6 +433,20 @@ func (p *Parser) parseFields(fields []Field) ([]Field, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// var name string
|
||||
|
||||
// if f.Alias != "" {
|
||||
// name = f.Alias
|
||||
// } else {
|
||||
// name = f.Name
|
||||
// }
|
||||
|
||||
// if _, ok := fm[name]; ok {
|
||||
// continue
|
||||
// } else {
|
||||
// fm[name] = struct{}{}
|
||||
// }
|
||||
|
||||
if st.Len() == 0 {
|
||||
f.ParentID = -1
|
||||
} else {
|
||||
@ -685,6 +716,16 @@ func (p *Parser) reset(to int) {
|
||||
p.pos = to
|
||||
}
|
||||
|
||||
func (p *Parser) fHash(name string, parentID int32) uint64 {
|
||||
var b []byte
|
||||
binary.LittleEndian.PutUint32(b, uint32(parentID))
|
||||
p.h.WriteString(name)
|
||||
p.h.Write(b)
|
||||
v := p.h.Sum64()
|
||||
p.h.Reset()
|
||||
return v
|
||||
}
|
||||
|
||||
func b2s(b []byte) string {
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
}
|
||||
|
@ -239,6 +239,29 @@ var gql = []byte(`
|
||||
price
|
||||
}}`)
|
||||
|
||||
var gqlWithFragments = []byte(`
|
||||
fragment userFields1 on user {
|
||||
id
|
||||
email
|
||||
__typename
|
||||
}
|
||||
|
||||
query {
|
||||
users {
|
||||
...userFields2
|
||||
|
||||
created_at
|
||||
...userFields1
|
||||
__typename
|
||||
}
|
||||
}
|
||||
|
||||
fragment userFields2 on user {
|
||||
first_name
|
||||
last_name
|
||||
__typename
|
||||
}`)
|
||||
|
||||
func BenchmarkQCompile(b *testing.B) {
|
||||
qcompile, _ := NewCompiler(Config{})
|
||||
|
||||
@ -271,6 +294,21 @@ func BenchmarkQCompileP(b *testing.B) {
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkQCompileFragment(b *testing.B) {
|
||||
qcompile, _ := NewCompiler(Config{})
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for n := 0; n < b.N; n++ {
|
||||
_, err := qcompile.Compile(gqlWithFragments, "user")
|
||||
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func BenchmarkParse(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
@ -298,6 +336,18 @@ func BenchmarkParseP(b *testing.B) {
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkParseFragment(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for n := 0; n < b.N; n++ {
|
||||
_, err := Parse(gqlWithFragments)
|
||||
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSchemaParse(b *testing.B) {
|
||||
|
||||
b.ResetTimer()
|
||||
|
@ -419,6 +419,7 @@ func (com *Compiler) compileQuery(qc *QCode, op *Operation, role string) error {
|
||||
com.AddFilters(qc, s, role)
|
||||
|
||||
s.Cols = make([]Column, 0, len(field.Children))
|
||||
cm := make(map[string]struct{})
|
||||
action = QTQuery
|
||||
|
||||
for _, cid := range field.Children {
|
||||
@ -428,19 +429,28 @@ func (com *Compiler) compileQuery(qc *QCode, op *Operation, role string) error {
|
||||
continue
|
||||
}
|
||||
|
||||
var fname string
|
||||
|
||||
if f.Alias != "" {
|
||||
fname = f.Alias
|
||||
} else {
|
||||
fname = f.Name
|
||||
}
|
||||
|
||||
if _, ok := cm[fname]; ok {
|
||||
continue
|
||||
} else {
|
||||
cm[fname] = struct{}{}
|
||||
}
|
||||
|
||||
if len(f.Children) != 0 {
|
||||
val := f.ID | (s.ID << 16)
|
||||
st.Push(val)
|
||||
continue
|
||||
}
|
||||
|
||||
col := Column{Name: f.Name}
|
||||
col := Column{Name: f.Name, FieldName: fname}
|
||||
|
||||
if len(f.Alias) != 0 {
|
||||
col.FieldName = f.Alias
|
||||
} else {
|
||||
col.FieldName = f.Name
|
||||
}
|
||||
s.Cols = append(s.Cols, col)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user