github.com/blong14/gache@v0.0.0-20240124023949-89416fd8bbfa/sql/sql.go (about) 1 package sql 2 3 import ( 4 "bufio" 5 "context" 6 "errors" 7 "io" 8 "strconv" 9 "strings" 10 11 gdb "github.com/blong14/gache/internal/db" 12 ) 13 14 type parseContext struct { 15 scanner *bufio.Scanner 16 query *gdb.Query 17 tkn string 18 evaluators map[string]func(s *bufio.Scanner, q *gdb.Query) error 19 } 20 21 func newParseContext(scanner *bufio.Scanner, query *gdb.Query) *parseContext { 22 return &parseContext{ 23 scanner: scanner, 24 query: query, 25 evaluators: map[string]func(s *bufio.Scanner, q *gdb.Query) error{ 26 "copy": func(scanner *bufio.Scanner, query *gdb.Query) error { 27 query.Header.Inst = gdb.Load 28 for scanner.Scan() { 29 switch scanner.Text() { 30 case "from": 31 if scanner.Scan() { 32 file := strings.TrimSpace(scanner.Text()) 33 if strings.HasSuffix(file, ";") { 34 query.Header.FileName = []byte(strings.TrimSuffix(file, ";")) 35 return nil 36 } 37 query.Header.FileName = []byte(file) 38 } 39 return nil 40 default: 41 table := strings.TrimSpace(scanner.Text()) 42 query.Header.TableName = []byte(table) 43 } 44 } 45 return nil 46 }, 47 "create": func(scanner *bufio.Scanner, query *gdb.Query) error { 48 query.Header.Inst = gdb.AddTable 49 return nil 50 }, 51 "from": func(scanner *bufio.Scanner, query *gdb.Query) error { 52 if scanner.Scan() { 53 table := strings.TrimSpace(scanner.Text()) 54 query.Header.TableName = []byte(strings.TrimSuffix(table, ";")) 55 } 56 return nil 57 }, 58 "insert": func(scanner *bufio.Scanner, query *gdb.Query) error { 59 query.Header.Inst = gdb.SetValue 60 return nil 61 }, 62 "key": func(scanner *bufio.Scanner, query *gdb.Query) error { 63 for scanner.Scan() { 64 switch scanner.Text() { 65 case "=": 66 if query.Header.Inst == gdb.GetRange { 67 query.Header.Inst = gdb.GetValue 68 } 69 continue 70 case "and": 71 if scanner.Scan() { 72 query.KeyRange.End = []byte(strings.TrimSuffix(scanner.Text(), ";")) 73 } 74 case "between": 75 if scanner.Scan() { 76 query.KeyRange.Start = []byte(scanner.Text()) 77 } 78 continue 79 default: 80 key := strings.TrimSpace(scanner.Text()) 81 if strings.HasSuffix(key, ";") { 82 query.Key = []byte(strings.TrimSuffix(key, ";")) 83 return nil 84 } 85 query.Key = []byte(strings.TrimSuffix(key, ",")) 86 } 87 break 88 } 89 return nil 90 }, 91 "select": func(scanner *bufio.Scanner, query *gdb.Query) error { 92 if scanner.Scan() { 93 query.Header.Inst = gdb.GetRange 94 switch scanner.Text() { 95 case "count": 96 query.Header.Inst = gdb.Count 97 default: 98 } 99 return nil 100 } 101 return errors.New("missing token") 102 }, 103 "into": func(scanner *bufio.Scanner, query *gdb.Query) error { 104 if scanner.Scan() { 105 table := strings.TrimSpace(scanner.Text()) 106 if strings.HasSuffix(table, ";") { 107 query.Header.TableName = []byte(strings.TrimSuffix(table, ";")) 108 return nil 109 } 110 query.Header.TableName = []byte(table) 111 return nil 112 } 113 return errors.New("missing table") 114 }, 115 "table": func(scanner *bufio.Scanner, query *gdb.Query) error { 116 if scanner.Scan() { 117 table := strings.TrimSpace(scanner.Text()) 118 if strings.HasSuffix(table, ";") { 119 query.Header.TableName = []byte(strings.TrimSuffix(table, ";")) 120 return nil 121 } 122 } 123 return errors.New("missing table") 124 }, 125 "value": func(scanner *bufio.Scanner, query *gdb.Query) error { 126 for scanner.Scan() { 127 switch scanner.Text() { 128 case "=": 129 continue 130 default: 131 value := strings.TrimSpace(scanner.Text()) 132 if strings.HasSuffix(value, ";") { 133 query.Value = []byte(strings.TrimSuffix(value, ";")) 134 return nil 135 } 136 query.Value = []byte(value) 137 } 138 break 139 } 140 return nil 141 }, 142 "limit": func(scanner *bufio.Scanner, query *gdb.Query) error { 143 if scanner.Scan() { 144 limit := strings.TrimSpace(scanner.Text()) 145 l, err := strconv.Atoi(strings.TrimSuffix(limit, ";")) 146 if err != nil { 147 l = 0 148 } 149 query.KeyRange.Limit = l 150 } 151 return nil 152 }, 153 }, 154 } 155 } 156 157 func (p *parseContext) SetToken(tkn string) { 158 p.tkn = tkn 159 } 160 161 func (p *parseContext) Evaluate() error { 162 if eval, ok := p.evaluators[p.tkn]; ok { 163 return eval(p.scanner, p.query) 164 } 165 return nil 166 } 167 168 func parse(src io.Reader) (*gdb.Query, error) { 169 scanner := bufio.NewScanner(src) 170 scanner.Split(bufio.ScanWords) 171 query := gdb.NewQuery(context.Background(), nil) 172 ctx := newParseContext(scanner, query) 173 for scanner.Scan() { 174 ctx.SetToken(scanner.Text()) 175 if err := ctx.Evaluate(); err != nil { 176 return nil, err 177 } 178 } 179 return query, nil 180 }