pqarrays
2015-04-19
Child:ce9c92fc81ab
pqarrays/array.go
First pass implementation. Use a lexer to generate tokens out of the Array type responses that PostgreSQL will send. Write a parser for string[] array types. Create a StringArray type that fulfills the driver.Valuer and sql.Scanner interfaces using the parser and lexer.
| paddy@0 | 1 package pqarrays |
| paddy@0 | 2 |
| paddy@0 | 3 import ( |
| paddy@0 | 4 "database/sql/driver" |
| paddy@0 | 5 "errors" |
| paddy@0 | 6 "strconv" |
| paddy@0 | 7 "strings" |
| paddy@0 | 8 ) |
| paddy@0 | 9 |
| paddy@0 | 10 var ( |
| paddy@0 | 11 ErrUnexpectedValueType = errors.New("expected value to be a string or []byte") |
| paddy@0 | 12 ) |
| paddy@0 | 13 |
| paddy@0 | 14 type StringArray []string |
| paddy@0 | 15 |
| paddy@0 | 16 func (s StringArray) Value() (driver.Value, error) { |
| paddy@0 | 17 output := make([]string, 0, len(s)) |
| paddy@0 | 18 for _, item := range s { |
| paddy@0 | 19 item = strconv.Quote(item) |
| paddy@0 | 20 item = strings.Replace(item, "'", "\\'", -1) |
| paddy@0 | 21 output = append(output, item) |
| paddy@0 | 22 } |
| paddy@0 | 23 return []byte(`{` + strings.Join(output, ",") + `}`), nil |
| paddy@0 | 24 } |
| paddy@0 | 25 |
| paddy@0 | 26 func (s *StringArray) Scan(value interface{}) error { |
| paddy@0 | 27 *s = (*s)[:0] |
| paddy@0 | 28 var input string |
| paddy@0 | 29 if _, ok := value.(string); ok { |
| paddy@0 | 30 input = value.(string) |
| paddy@0 | 31 } else if _, ok := value.([]byte); ok { |
| paddy@0 | 32 input = string(value.([]byte)) |
| paddy@0 | 33 } else { |
| paddy@0 | 34 return ErrUnexpectedValueType |
| paddy@0 | 35 } |
| paddy@0 | 36 l := lex(input) |
| paddy@0 | 37 parsed, err := parse(l) |
| paddy@0 | 38 if err != nil { |
| paddy@0 | 39 return err |
| paddy@0 | 40 } |
| paddy@0 | 41 for _, item := range parsed { |
| paddy@0 | 42 if item == nil { |
| paddy@0 | 43 continue |
| paddy@0 | 44 } |
| paddy@0 | 45 *s = append(*s, *item) |
| paddy@0 | 46 } |
| paddy@0 | 47 return nil |
| paddy@0 | 48 } |