summaryrefslogtreecommitdiff
path: root/vendor/github.com/uptrace/bun/dialect
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/uptrace/bun/dialect')
-rw-r--r--vendor/github.com/uptrace/bun/dialect/feature/feature.go2
-rw-r--r--vendor/github.com/uptrace/bun/dialect/pgdialect/append.go55
-rw-r--r--vendor/github.com/uptrace/bun/dialect/pgdialect/array_parser.go36
-rw-r--r--vendor/github.com/uptrace/bun/dialect/pgdialect/dialect.go10
-rw-r--r--vendor/github.com/uptrace/bun/dialect/pgdialect/hstore.go73
-rw-r--r--vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_parser.go142
-rw-r--r--vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_scan.go82
-rw-r--r--vendor/github.com/uptrace/bun/dialect/pgdialect/sqltype.go6
-rw-r--r--vendor/github.com/uptrace/bun/dialect/pgdialect/stream_parser.go60
-rw-r--r--vendor/github.com/uptrace/bun/dialect/pgdialect/version.go2
-rw-r--r--vendor/github.com/uptrace/bun/dialect/sqlitedialect/version.go2
-rw-r--r--vendor/github.com/uptrace/bun/dialect/sqltype/sqltype.go1
12 files changed, 430 insertions, 41 deletions
diff --git a/vendor/github.com/uptrace/bun/dialect/feature/feature.go b/vendor/github.com/uptrace/bun/dialect/feature/feature.go
index 510d6e5de..956dc4985 100644
--- a/vendor/github.com/uptrace/bun/dialect/feature/feature.go
+++ b/vendor/github.com/uptrace/bun/dialect/feature/feature.go
@@ -29,4 +29,6 @@ const (
OffsetFetch
SelectExists
UpdateFromTable
+ MSSavepoint
+ GeneratedIdentity
)
diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/append.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/append.go
index d5e0d0a57..a60bf5de2 100644
--- a/vendor/github.com/uptrace/bun/dialect/pgdialect/append.go
+++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/append.go
@@ -307,3 +307,58 @@ func arrayAppendString(b []byte, s string) []byte {
b = append(b, '"')
return b
}
+
+//------------------------------------------------------------------------------
+
+var mapStringStringType = reflect.TypeOf(map[string]string(nil))
+
+func (d *Dialect) hstoreAppender(typ reflect.Type) schema.AppenderFunc {
+ kind := typ.Kind()
+
+ switch kind {
+ case reflect.Ptr:
+ if fn := d.hstoreAppender(typ.Elem()); fn != nil {
+ return schema.PtrAppender(fn)
+ }
+ case reflect.Map:
+ // ok:
+ default:
+ return nil
+ }
+
+ if typ.Key() == stringType && typ.Elem() == stringType {
+ return appendMapStringStringValue
+ }
+
+ return func(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
+ err := fmt.Errorf("bun: Hstore(unsupported %s)", v.Type())
+ return dialect.AppendError(b, err)
+ }
+}
+
+func appendMapStringString(b []byte, m map[string]string) []byte {
+ if m == nil {
+ return dialect.AppendNull(b)
+ }
+
+ b = append(b, '\'')
+
+ for key, value := range m {
+ b = arrayAppendString(b, key)
+ b = append(b, '=', '>')
+ b = arrayAppendString(b, value)
+ b = append(b, ',')
+ }
+ if len(m) > 0 {
+ b = b[:len(b)-1] // Strip trailing comma.
+ }
+
+ b = append(b, '\'')
+
+ return b
+}
+
+func appendMapStringStringValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
+ m := v.Convert(mapStringStringType).Interface().(map[string]string)
+ return appendMapStringString(b, m)
+}
diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/array_parser.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/array_parser.go
index 0dff754f8..a8358337e 100644
--- a/vendor/github.com/uptrace/bun/dialect/pgdialect/array_parser.go
+++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/array_parser.go
@@ -8,17 +8,13 @@ import (
)
type arrayParser struct {
- b []byte
- i int
-
- buf []byte
+ *streamParser
err error
}
func newArrayParser(b []byte) *arrayParser {
p := &arrayParser{
- b: b,
- i: 1,
+ streamParser: newStreamParser(b, 1),
}
if len(b) < 2 || b[0] != '{' || b[len(b)-1] != '}' {
p.err = fmt.Errorf("bun: can't parse array: %q", b)
@@ -135,31 +131,3 @@ func (p *arrayParser) readSubstring() ([]byte, error) {
return p.buf, nil
}
-
-func (p *arrayParser) valid() bool {
- return p.i < len(p.b)
-}
-
-func (p *arrayParser) readByte() (byte, error) {
- if p.valid() {
- c := p.b[p.i]
- p.i++
- return c, nil
- }
- return 0, io.EOF
-}
-
-func (p *arrayParser) unreadByte() {
- p.i--
-}
-
-func (p *arrayParser) peek() byte {
- if p.valid() {
- return p.b[p.i]
- }
- return 0
-}
-
-func (p *arrayParser) skipNext() {
- p.i++
-}
diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/dialect.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/dialect.go
index 852132b7f..d524f0a1a 100644
--- a/vendor/github.com/uptrace/bun/dialect/pgdialect/dialect.go
+++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/dialect.go
@@ -46,7 +46,8 @@ func New() *Dialect {
feature.TableTruncate |
feature.TableNotExists |
feature.InsertOnConflict |
- feature.SelectExists
+ feature.SelectExists |
+ feature.GeneratedIdentity
return d
}
@@ -73,7 +74,7 @@ func (d *Dialect) OnTable(table *schema.Table) {
func (d *Dialect) onField(field *schema.Field) {
field.DiscoveredSQLType = fieldSQLType(field)
- if field.AutoIncrement {
+ if field.AutoIncrement && !field.Identity {
switch field.DiscoveredSQLType {
case sqltype.SmallInt:
field.CreateTableSQLType = pgTypeSmallSerial
@@ -88,6 +89,11 @@ func (d *Dialect) onField(field *schema.Field) {
field.Append = d.arrayAppender(field.StructField.Type)
field.Scan = arrayScanner(field.StructField.Type)
}
+
+ if field.DiscoveredSQLType == sqltype.HSTORE {
+ field.Append = d.hstoreAppender(field.StructField.Type)
+ field.Scan = hstoreScanner(field.StructField.Type)
+ }
}
func (d *Dialect) IdentQuote() byte {
diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/hstore.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/hstore.go
new file mode 100644
index 000000000..029f7cb6d
--- /dev/null
+++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/hstore.go
@@ -0,0 +1,73 @@
+package pgdialect
+
+import (
+ "database/sql"
+ "fmt"
+ "reflect"
+
+ "github.com/uptrace/bun/schema"
+)
+
+type HStoreValue struct {
+ v reflect.Value
+
+ append schema.AppenderFunc
+ scan schema.ScannerFunc
+}
+
+// HStore accepts a map[string]string and returns a wrapper for working with PostgreSQL
+// hstore data type.
+//
+// For struct fields you can use hstore tag:
+//
+// Attrs map[string]string `bun:",hstore"`
+func HStore(vi interface{}) *HStoreValue {
+ v := reflect.ValueOf(vi)
+ if !v.IsValid() {
+ panic(fmt.Errorf("bun: HStore(nil)"))
+ }
+
+ typ := v.Type()
+ if typ.Kind() == reflect.Ptr {
+ typ = typ.Elem()
+ }
+ if typ.Kind() != reflect.Map {
+ panic(fmt.Errorf("bun: Hstore(unsupported %s)", typ))
+ }
+
+ return &HStoreValue{
+ v: v,
+
+ append: pgDialect.hstoreAppender(v.Type()),
+ scan: hstoreScanner(v.Type()),
+ }
+}
+
+var (
+ _ schema.QueryAppender = (*HStoreValue)(nil)
+ _ sql.Scanner = (*HStoreValue)(nil)
+)
+
+func (h *HStoreValue) AppendQuery(fmter schema.Formatter, b []byte) ([]byte, error) {
+ if h.append == nil {
+ panic(fmt.Errorf("bun: HStore(unsupported %s)", h.v.Type()))
+ }
+ return h.append(fmter, b, h.v), nil
+}
+
+func (h *HStoreValue) Scan(src interface{}) error {
+ if h.scan == nil {
+ return fmt.Errorf("bun: HStore(unsupported %s)", h.v.Type())
+ }
+ if h.v.Kind() != reflect.Ptr {
+ return fmt.Errorf("bun: HStore(non-pointer %s)", h.v.Type())
+ }
+ return h.scan(h.v.Elem(), src)
+}
+
+func (h *HStoreValue) Value() interface{} {
+ if h.v.IsValid() {
+ return h.v.Interface()
+ }
+ return nil
+}
diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_parser.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_parser.go
new file mode 100644
index 000000000..7a18b50b1
--- /dev/null
+++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_parser.go
@@ -0,0 +1,142 @@
+package pgdialect
+
+import (
+ "bytes"
+ "fmt"
+)
+
+type hstoreParser struct {
+ *streamParser
+ err error
+}
+
+func newHStoreParser(b []byte) *hstoreParser {
+ p := &hstoreParser{
+ streamParser: newStreamParser(b, 0),
+ }
+ if len(b) < 6 || b[0] != '"' {
+ p.err = fmt.Errorf("bun: can't parse hstore: %q", b)
+ }
+ return p
+}
+
+func (p *hstoreParser) NextKey() (string, error) {
+ if p.err != nil {
+ return "", p.err
+ }
+
+ err := p.skipByte('"')
+ if err != nil {
+ return "", err
+ }
+
+ key, err := p.readSubstring()
+ if err != nil {
+ return "", err
+ }
+
+ const separator = "=>"
+
+ for i := range separator {
+ err = p.skipByte(separator[i])
+ if err != nil {
+ return "", err
+ }
+ }
+
+ return string(key), nil
+}
+
+func (p *hstoreParser) NextValue() (string, error) {
+ if p.err != nil {
+ return "", p.err
+ }
+
+ c, err := p.readByte()
+ if err != nil {
+ return "", err
+ }
+
+ switch c {
+ case '"':
+ value, err := p.readSubstring()
+ if err != nil {
+ return "", err
+ }
+
+ if p.peek() == ',' {
+ p.skipNext()
+ }
+
+ if p.peek() == ' ' {
+ p.skipNext()
+ }
+
+ return string(value), nil
+ default:
+ value := p.readSimple()
+ if bytes.Equal(value, []byte("NULL")) {
+ value = nil
+ }
+
+ if p.peek() == ',' {
+ p.skipNext()
+ }
+
+ return string(value), nil
+ }
+}
+
+func (p *hstoreParser) readSimple() []byte {
+ p.unreadByte()
+
+ if i := bytes.IndexByte(p.b[p.i:], ','); i >= 0 {
+ b := p.b[p.i : p.i+i]
+ p.i += i
+ return b
+ }
+
+ b := p.b[p.i:len(p.b)]
+ p.i = len(p.b)
+ return b
+}
+
+func (p *hstoreParser) readSubstring() ([]byte, error) {
+ c, err := p.readByte()
+ if err != nil {
+ return nil, err
+ }
+
+ p.buf = p.buf[:0]
+ for {
+ if c == '"' {
+ break
+ }
+
+ next, err := p.readByte()
+ if err != nil {
+ return nil, err
+ }
+
+ if c == '\\' {
+ switch next {
+ case '\\', '"':
+ p.buf = append(p.buf, next)
+
+ c, err = p.readByte()
+ if err != nil {
+ return nil, err
+ }
+ default:
+ p.buf = append(p.buf, '\\')
+ c = next
+ }
+ continue
+ }
+
+ p.buf = append(p.buf, c)
+ c = next
+ }
+
+ return p.buf, nil
+}
diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_scan.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_scan.go
new file mode 100644
index 000000000..b10b06b8d
--- /dev/null
+++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_scan.go
@@ -0,0 +1,82 @@
+package pgdialect
+
+import (
+ "fmt"
+ "io"
+ "reflect"
+
+ "github.com/uptrace/bun/schema"
+)
+
+func hstoreScanner(typ reflect.Type) schema.ScannerFunc {
+ kind := typ.Kind()
+
+ switch kind {
+ case reflect.Ptr:
+ if fn := hstoreScanner(typ.Elem()); fn != nil {
+ return schema.PtrScanner(fn)
+ }
+ case reflect.Map:
+ // ok:
+ default:
+ return nil
+ }
+
+ if typ.Key() == stringType && typ.Elem() == stringType {
+ return scanMapStringStringValue
+ }
+ return func(dest reflect.Value, src interface{}) error {
+ return fmt.Errorf("bun: Hstore(unsupported %s)", dest.Type())
+ }
+}
+
+func scanMapStringStringValue(dest reflect.Value, src interface{}) error {
+ dest = reflect.Indirect(dest)
+ if !dest.CanSet() {
+ return fmt.Errorf("bun: Scan(non-settable %s)", dest.Type())
+ }
+
+ m, err := decodeMapStringString(src)
+ if err != nil {
+ return err
+ }
+
+ dest.Set(reflect.ValueOf(m))
+ return nil
+}
+
+func decodeMapStringString(src interface{}) (map[string]string, error) {
+ if src == nil {
+ return nil, nil
+ }
+
+ b, err := toBytes(src)
+ if err != nil {
+ return nil, err
+ }
+
+ m := make(map[string]string)
+
+ p := newHStoreParser(b)
+ for {
+ key, err := p.NextKey()
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ return nil, err
+ }
+
+ value, err := p.NextValue()
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ return nil, err
+ }
+
+ m[key] = value
+ }
+
+ return m, nil
+}
diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/sqltype.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/sqltype.go
index bfef89fa1..6c6294d71 100644
--- a/vendor/github.com/uptrace/bun/dialect/pgdialect/sqltype.go
+++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/sqltype.go
@@ -53,11 +53,11 @@ func fieldSQLType(field *schema.Field) string {
if v, ok := field.Tag.Option("composite"); ok {
return v
}
- if _, ok := field.Tag.Option("hstore"); ok {
- return "hstore"
+ if field.Tag.HasOption("hstore") {
+ return sqltype.HSTORE
}
- if _, ok := field.Tag.Options["array"]; ok {
+ if field.Tag.HasOption("array") {
switch field.IndirectType.Kind() {
case reflect.Slice, reflect.Array:
sqlType := sqlType(field.IndirectType.Elem())
diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/stream_parser.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/stream_parser.go
new file mode 100644
index 000000000..7b9a15f62
--- /dev/null
+++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/stream_parser.go
@@ -0,0 +1,60 @@
+package pgdialect
+
+import (
+ "fmt"
+ "io"
+)
+
+type streamParser struct {
+ b []byte
+ i int
+
+ buf []byte
+}
+
+func newStreamParser(b []byte, start int) *streamParser {
+ return &streamParser{
+ b: b,
+ i: start,
+ }
+}
+
+func (p *streamParser) valid() bool {
+ return p.i < len(p.b)
+}
+
+func (p *streamParser) skipByte(skip byte) error {
+ c, err := p.readByte()
+ if err != nil {
+ return err
+ }
+ if c == skip {
+ return nil
+ }
+ p.unreadByte()
+ return fmt.Errorf("got %q, wanted %q", c, skip)
+}
+
+func (p *streamParser) readByte() (byte, error) {
+ if p.valid() {
+ c := p.b[p.i]
+ p.i++
+ return c, nil
+ }
+ return 0, io.EOF
+}
+
+func (p *streamParser) unreadByte() {
+ p.i--
+}
+
+func (p *streamParser) peek() byte {
+ if p.valid() {
+ return p.b[p.i]
+ }
+ return 0
+}
+
+func (p *streamParser) skipNext() {
+ p.i++
+}
diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/version.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/version.go
index a3adb36aa..8ab18b7a7 100644
--- a/vendor/github.com/uptrace/bun/dialect/pgdialect/version.go
+++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/version.go
@@ -2,5 +2,5 @@ package pgdialect
// Version is the current release version.
func Version() string {
- return "1.1.3"
+ return "1.1.7"
}
diff --git a/vendor/github.com/uptrace/bun/dialect/sqlitedialect/version.go b/vendor/github.com/uptrace/bun/dialect/sqlitedialect/version.go
index 76a755a86..8f9def8d0 100644
--- a/vendor/github.com/uptrace/bun/dialect/sqlitedialect/version.go
+++ b/vendor/github.com/uptrace/bun/dialect/sqlitedialect/version.go
@@ -2,5 +2,5 @@ package sqlitedialect
// Version is the current release version.
func Version() string {
- return "1.1.3"
+ return "1.1.7"
}
diff --git a/vendor/github.com/uptrace/bun/dialect/sqltype/sqltype.go b/vendor/github.com/uptrace/bun/dialect/sqltype/sqltype.go
index f58b2f1d1..1031fd352 100644
--- a/vendor/github.com/uptrace/bun/dialect/sqltype/sqltype.go
+++ b/vendor/github.com/uptrace/bun/dialect/sqltype/sqltype.go
@@ -12,4 +12,5 @@ const (
Timestamp = "TIMESTAMP"
JSON = "JSON"
JSONB = "JSONB"
+ HSTORE = "HSTORE"
)