pqarrays
pqarrays/array.go
Fix bug parsing empty arrays, make golint and go vet happy. Add comments to make golint happy. Also, because comments are a good thing to have. Turn += 1 and -= 1 into ++ and --, respectively, so golint will be happy. Fix an improperly formated errorf, where a rune was being treated as a string. Thanks, go vet! Fix whitespace parsing, returning the parse functions again instead of just skipping the one character. Now if we have more than one whitespace character in a row, they'll all be skipped. Add a parseStringOrNullOrEnd parse function that will be called after the tokenArrayStart character, to fix a bug where empty arrays were expecting a string or null and getting the array end character. This is only valid after tokenArrayStart, however; in other places where parseSeparatorOrDelim is used, it wouldn't be appropriate. Add a parser test for an empty array.
| 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@1 | 11 // ErrUnexpectedValueType is returned when the passed value is not a string or []byte. |
| paddy@0 | 12 ErrUnexpectedValueType = errors.New("expected value to be a string or []byte") |
| paddy@0 | 13 ) |
| paddy@0 | 14 |
| paddy@1 | 15 // StringArray represents a Postgres array as a []string. |
| paddy@0 | 16 type StringArray []string |
| paddy@0 | 17 |
| paddy@1 | 18 // Value implements the Valuer interface for StringArray, allowing it to be transparently |
| paddy@1 | 19 // stored in Postgres databases using the database/sql package. |
| paddy@0 | 20 func (s StringArray) Value() (driver.Value, error) { |
| paddy@0 | 21 output := make([]string, 0, len(s)) |
| paddy@0 | 22 for _, item := range s { |
| paddy@0 | 23 item = strconv.Quote(item) |
| paddy@0 | 24 item = strings.Replace(item, "'", "\\'", -1) |
| paddy@0 | 25 output = append(output, item) |
| paddy@0 | 26 } |
| paddy@0 | 27 return []byte(`{` + strings.Join(output, ",") + `}`), nil |
| paddy@0 | 28 } |
| paddy@0 | 29 |
| paddy@1 | 30 // Scan implements the Scanner interface for StringArray, allowing it to be transparently |
| paddy@1 | 31 // retrieved from Postgres databases using the database/sql package. It expects `value` to |
| paddy@1 | 32 // be a string or []byte, and throws ErrUnexpectedValueType when any other type is encountered. |
| paddy@0 | 33 func (s *StringArray) Scan(value interface{}) error { |
| paddy@0 | 34 *s = (*s)[:0] |
| paddy@0 | 35 var input string |
| paddy@0 | 36 if _, ok := value.(string); ok { |
| paddy@0 | 37 input = value.(string) |
| paddy@0 | 38 } else if _, ok := value.([]byte); ok { |
| paddy@0 | 39 input = string(value.([]byte)) |
| paddy@0 | 40 } else { |
| paddy@0 | 41 return ErrUnexpectedValueType |
| paddy@0 | 42 } |
| paddy@0 | 43 l := lex(input) |
| paddy@0 | 44 parsed, err := parse(l) |
| paddy@0 | 45 if err != nil { |
| paddy@0 | 46 return err |
| paddy@0 | 47 } |
| paddy@0 | 48 for _, item := range parsed { |
| paddy@0 | 49 if item == nil { |
| paddy@0 | 50 continue |
| paddy@0 | 51 } |
| paddy@0 | 52 *s = append(*s, *item) |
| paddy@0 | 53 } |
| paddy@0 | 54 return nil |
| paddy@0 | 55 } |