提交 86bcdec5 编写于 作者: martianzhang's avatar martianzhang

update vendor

上级 cd17cced
......@@ -31,8 +31,33 @@
package proto
import "errors"
// Deprecated: do not use.
type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 }
// Deprecated: do not use.
func GetStats() Stats { return Stats{} }
// Deprecated: do not use.
func MarshalMessageSet(interface{}) ([]byte, error) {
return nil, errors.New("proto: not implemented")
}
// Deprecated: do not use.
func UnmarshalMessageSet([]byte, interface{}) error {
return errors.New("proto: not implemented")
}
// Deprecated: do not use.
func MarshalMessageSetJSON(interface{}) ([]byte, error) {
return nil, errors.New("proto: not implemented")
}
// Deprecated: do not use.
func UnmarshalMessageSetJSON([]byte, interface{}) error {
return errors.New("proto: not implemented")
}
// Deprecated: do not use.
func RegisterMessageSetType(Message, int32, string) {}
......@@ -246,7 +246,8 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
return false
}
m1, m2 := e1.value, e2.value
m1 := extensionAsLegacyType(e1.value)
m2 := extensionAsLegacyType(e2.value)
if m1 == nil && m2 == nil {
// Both have only encoded form.
......
......@@ -185,9 +185,25 @@ type Extension struct {
// extension will have only enc set. When such an extension is
// accessed using GetExtension (or GetExtensions) desc and value
// will be set.
desc *ExtensionDesc
desc *ExtensionDesc
// value is a concrete value for the extension field. Let the type of
// desc.ExtensionType be the "API type" and the type of Extension.value
// be the "storage type". The API type and storage type are the same except:
// * For scalars (except []byte), the API type uses *T,
// while the storage type uses T.
// * For repeated fields, the API type uses []T, while the storage type
// uses *[]T.
//
// The reason for the divergence is so that the storage type more naturally
// matches what is expected of when retrieving the values through the
// protobuf reflection APIs.
//
// The value may only be populated if desc is also populated.
value interface{}
enc []byte
// enc is the raw bytes for the extension field.
enc []byte
}
// SetRawExtension is for testing only.
......@@ -334,7 +350,7 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
// descriptors with the same field number.
return nil, errors.New("proto: descriptor conflict")
}
return e.value, nil
return extensionAsLegacyType(e.value), nil
}
if extension.ExtensionType == nil {
......@@ -349,11 +365,11 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
// Remember the decoded version and drop the encoded version.
// That way it is safe to mutate what we return.
e.value = v
e.value = extensionAsStorageType(v)
e.desc = extension
e.enc = nil
emap[extension.Field] = e
return e.value, nil
return extensionAsLegacyType(e.value), nil
}
// defaultExtensionValue returns the default value for extension.
......@@ -500,7 +516,7 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error
}
extmap := epb.extensionsWrite()
extmap[extension.Field] = Extension{desc: extension, value: value}
extmap[extension.Field] = Extension{desc: extension, value: extensionAsStorageType(value)}
return nil
}
......@@ -541,3 +557,51 @@ func RegisterExtension(desc *ExtensionDesc) {
func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
return extensionMaps[reflect.TypeOf(pb).Elem()]
}
// extensionAsLegacyType converts an value in the storage type as the API type.
// See Extension.value.
func extensionAsLegacyType(v interface{}) interface{} {
switch rv := reflect.ValueOf(v); rv.Kind() {
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
// Represent primitive types as a pointer to the value.
rv2 := reflect.New(rv.Type())
rv2.Elem().Set(rv)
v = rv2.Interface()
case reflect.Ptr:
// Represent slice types as the value itself.
switch rv.Type().Elem().Kind() {
case reflect.Slice:
if rv.IsNil() {
v = reflect.Zero(rv.Type().Elem()).Interface()
} else {
v = rv.Elem().Interface()
}
}
}
return v
}
// extensionAsStorageType converts an value in the API type as the storage type.
// See Extension.value.
func extensionAsStorageType(v interface{}) interface{} {
switch rv := reflect.ValueOf(v); rv.Kind() {
case reflect.Ptr:
// Represent slice types as the value itself.
switch rv.Type().Elem().Kind() {
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
if rv.IsNil() {
v = reflect.Zero(rv.Type().Elem()).Interface()
} else {
v = rv.Elem().Interface()
}
}
case reflect.Slice:
// Represent slice types as a pointer to the value.
if rv.Type().Elem().Kind() != reflect.Uint8 {
rv2 := reflect.New(rv.Type())
rv2.Elem().Set(rv)
v = rv2.Interface()
}
}
return v
}
......@@ -940,13 +940,19 @@ func isProto3Zero(v reflect.Value) bool {
return false
}
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
const ProtoPackageIsVersion2 = true
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
const ProtoPackageIsVersion1 = true
const (
// ProtoPackageIsVersion3 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
ProtoPackageIsVersion3 = true
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
ProtoPackageIsVersion2 = true
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
ProtoPackageIsVersion1 = true
)
// InternalMessageInfo is a type used internally by generated .pb.go files.
// This type is not intended to be used by non-generated code.
......
......@@ -36,13 +36,7 @@ package proto
*/
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"reflect"
"sort"
"sync"
)
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
......@@ -145,46 +139,9 @@ func skipVarint(buf []byte) []byte {
return buf[i+1:]
}
// MarshalMessageSet encodes the extension map represented by m in the message set wire format.
// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
func MarshalMessageSet(exts interface{}) ([]byte, error) {
return marshalMessageSet(exts, false)
}
// marshaMessageSet implements above function, with the opt to turn on / off deterministic during Marshal.
func marshalMessageSet(exts interface{}, deterministic bool) ([]byte, error) {
switch exts := exts.(type) {
case *XXX_InternalExtensions:
var u marshalInfo
siz := u.sizeMessageSet(exts)
b := make([]byte, 0, siz)
return u.appendMessageSet(b, exts, deterministic)
case map[int32]Extension:
// This is an old-style extension map.
// Wrap it in a new-style XXX_InternalExtensions.
ie := XXX_InternalExtensions{
p: &struct {
mu sync.Mutex
extensionMap map[int32]Extension
}{
extensionMap: exts,
},
}
var u marshalInfo
siz := u.sizeMessageSet(&ie)
b := make([]byte, 0, siz)
return u.appendMessageSet(b, &ie, deterministic)
default:
return nil, errors.New("proto: not an extension map")
}
}
// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
// unmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
func UnmarshalMessageSet(buf []byte, exts interface{}) error {
func unmarshalMessageSet(buf []byte, exts interface{}) error {
var m map[int32]Extension
switch exts := exts.(type) {
case *XXX_InternalExtensions:
......@@ -222,93 +179,3 @@ func UnmarshalMessageSet(buf []byte, exts interface{}) error {
}
return nil
}
// MarshalMessageSetJSON encodes the extension map represented by m in JSON format.
// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
var m map[int32]Extension
switch exts := exts.(type) {
case *XXX_InternalExtensions:
var mu sync.Locker
m, mu = exts.extensionsRead()
if m != nil {
// Keep the extensions map locked until we're done marshaling to prevent
// races between marshaling and unmarshaling the lazily-{en,de}coded
// values.
mu.Lock()
defer mu.Unlock()
}
case map[int32]Extension:
m = exts
default:
return nil, errors.New("proto: not an extension map")
}
var b bytes.Buffer
b.WriteByte('{')
// Process the map in key order for deterministic output.
ids := make([]int32, 0, len(m))
for id := range m {
ids = append(ids, id)
}
sort.Sort(int32Slice(ids)) // int32Slice defined in text.go
for i, id := range ids {
ext := m[id]
msd, ok := messageSetMap[id]
if !ok {
// Unknown type; we can't render it, so skip it.
continue
}
if i > 0 && b.Len() > 1 {
b.WriteByte(',')
}
fmt.Fprintf(&b, `"[%s]":`, msd.name)
x := ext.value
if x == nil {
x = reflect.New(msd.t.Elem()).Interface()
if err := Unmarshal(ext.enc, x.(Message)); err != nil {
return nil, err
}
}
d, err := json.Marshal(x)
if err != nil {
return nil, err
}
b.Write(d)
}
b.WriteByte('}')
return b.Bytes(), nil
}
// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format.
// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error {
// Common-case fast path.
if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) {
return nil
}
// This is fairly tricky, and it's not clear that it is needed.
return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented")
}
// A global registry of types that can be used in a MessageSet.
var messageSetMap = make(map[int32]messageSetDesc)
type messageSetDesc struct {
t reflect.Type // pointer to struct
name string
}
// RegisterMessageSetType is called from the generated code.
func RegisterMessageSetType(m Message, fieldNum int32, name string) {
messageSetMap[fieldNum] = messageSetDesc{
t: reflect.TypeOf(m),
name: name,
}
}
......@@ -79,10 +79,13 @@ func toPointer(i *Message) pointer {
// toAddrPointer converts an interface to a pointer that points to
// the interface data.
func toAddrPointer(i *interface{}, isptr bool) pointer {
func toAddrPointer(i *interface{}, isptr, deref bool) pointer {
v := reflect.ValueOf(*i)
u := reflect.New(v.Type())
u.Elem().Set(v)
if deref {
u = u.Elem()
}
return pointer{v: u}
}
......
......@@ -85,16 +85,21 @@ func toPointer(i *Message) pointer {
// toAddrPointer converts an interface to a pointer that points to
// the interface data.
func toAddrPointer(i *interface{}, isptr bool) pointer {
func toAddrPointer(i *interface{}, isptr, deref bool) (p pointer) {
// Super-tricky - read or get the address of data word of interface value.
if isptr {
// The interface is of pointer type, thus it is a direct interface.
// The data word is the pointer data itself. We take its address.
return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
p = pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
} else {
// The interface is not of pointer type. The data word is the pointer
// to the data.
p = pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
}
// The interface is not of pointer type. The data word is the pointer
// to the data.
return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
if deref {
p.p = *(*unsafe.Pointer)(p.p)
}
return p
}
// valToPointer converts v to a pointer. v must be of pointer type.
......
......@@ -38,7 +38,6 @@ package proto
import (
"fmt"
"log"
"os"
"reflect"
"sort"
"strconv"
......@@ -194,7 +193,7 @@ func (p *Properties) Parse(s string) {
// "bytes,49,opt,name=foo,def=hello!"
fields := strings.Split(s, ",") // breaks def=, but handled below.
if len(fields) < 2 {
fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
log.Printf("proto: tag has too few fields: %q", s)
return
}
......@@ -214,7 +213,7 @@ func (p *Properties) Parse(s string) {
p.WireType = WireBytes
// no numeric converter for non-numeric types
default:
fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
log.Printf("proto: tag has unknown wire type: %q", s)
return
}
......@@ -343,6 +342,15 @@ func GetProperties(t reflect.Type) *StructProperties {
return sprop
}
type (
oneofFuncsIface interface {
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
}
oneofWrappersIface interface {
XXX_OneofWrappers() []interface{}
}
)
// getPropertiesLocked requires that propertiesMu is held.
func getPropertiesLocked(t reflect.Type) *StructProperties {
if prop, ok := propertiesMap[t]; ok {
......@@ -382,13 +390,14 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
// Re-order prop.order.
sort.Sort(prop)
type oneofMessage interface {
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
var oots []interface{}
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
case oneofFuncsIface:
_, _, _, oots = m.XXX_OneofFuncs()
case oneofWrappersIface:
oots = m.XXX_OneofWrappers()
}
if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
var oots []interface{}
_, _, _, oots = om.XXX_OneofFuncs()
if len(oots) > 0 {
// Interpret oneof metadata.
prop.OneofTypes = make(map[string]*OneofProperties)
for _, oot := range oots {
......
......@@ -87,6 +87,7 @@ type marshalElemInfo struct {
sizer sizer
marshaler marshaler
isptr bool // elem is pointer typed, thus interface of this type is a direct interface (extension only)
deref bool // dereference the pointer before operating on it; implies isptr
}
var (
......@@ -320,8 +321,11 @@ func (u *marshalInfo) computeMarshalInfo() {
// get oneof implementers
var oneofImplementers []interface{}
if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
case oneofFuncsIface:
_, _, _, oneofImplementers = m.XXX_OneofFuncs()
case oneofWrappersIface:
oneofImplementers = m.XXX_OneofWrappers()
}
n := t.NumField()
......@@ -407,13 +411,22 @@ func (u *marshalInfo) getExtElemInfo(desc *ExtensionDesc) *marshalElemInfo {
panic("tag is not an integer")
}
wt := wiretype(tags[0])
if t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct {
t = t.Elem()
}
sizer, marshaler := typeMarshaler(t, tags, false, false)
var deref bool
if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 {
t = reflect.PtrTo(t)
deref = true
}
e = &marshalElemInfo{
wiretag: uint64(tag)<<3 | wt,
tagsize: SizeVarint(uint64(tag) << 3),
sizer: sizer,
marshaler: marshaler,
isptr: t.Kind() == reflect.Ptr,
deref: deref,
}
// update cache
......@@ -476,10 +489,6 @@ func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofI
}
}
type oneofMessage interface {
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
}
// wiretype returns the wire encoding of the type.
func wiretype(encoding string) uint64 {
switch encoding {
......@@ -2310,8 +2319,8 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
for _, k := range m.MapKeys() {
ki := k.Interface()
vi := m.MapIndex(k).Interface()
kaddr := toAddrPointer(&ki, false) // pointer to key
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
kaddr := toAddrPointer(&ki, false, false) // pointer to key
vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value
siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
n += siz + SizeVarint(uint64(siz)) + tagsize
}
......@@ -2329,8 +2338,8 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
for _, k := range keys {
ki := k.Interface()
vi := m.MapIndex(k).Interface()
kaddr := toAddrPointer(&ki, false) // pointer to key
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
kaddr := toAddrPointer(&ki, false, false) // pointer to key
vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value
b = appendVarint(b, tag)
siz := keySizer(kaddr, 1) + valCachedSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
b = appendVarint(b, uint64(siz))
......@@ -2399,7 +2408,7 @@ func (u *marshalInfo) sizeExtensions(ext *XXX_InternalExtensions) int {
// the last time this function was called.
ei := u.getExtElemInfo(e.desc)
v := e.value
p := toAddrPointer(&v, ei.isptr)
p := toAddrPointer(&v, ei.isptr, ei.deref)
n += ei.sizer(p, ei.tagsize)
}
mu.Unlock()
......@@ -2434,7 +2443,7 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
ei := u.getExtElemInfo(e.desc)
v := e.value
p := toAddrPointer(&v, ei.isptr)
p := toAddrPointer(&v, ei.isptr, ei.deref)
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
if !nerr.Merge(err) {
return b, err
......@@ -2465,7 +2474,7 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
ei := u.getExtElemInfo(e.desc)
v := e.value
p := toAddrPointer(&v, ei.isptr)
p := toAddrPointer(&v, ei.isptr, ei.deref)
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
if !nerr.Merge(err) {
return b, err
......@@ -2510,7 +2519,7 @@ func (u *marshalInfo) sizeMessageSet(ext *XXX_InternalExtensions) int {
ei := u.getExtElemInfo(e.desc)
v := e.value
p := toAddrPointer(&v, ei.isptr)
p := toAddrPointer(&v, ei.isptr, ei.deref)
n += ei.sizer(p, 1) // message, tag = 3 (size=1)
}
mu.Unlock()
......@@ -2553,7 +2562,7 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
ei := u.getExtElemInfo(e.desc)
v := e.value
p := toAddrPointer(&v, ei.isptr)
p := toAddrPointer(&v, ei.isptr, ei.deref)
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
if !nerr.Merge(err) {
return b, err
......@@ -2591,7 +2600,7 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
ei := u.getExtElemInfo(e.desc)
v := e.value
p := toAddrPointer(&v, ei.isptr)
p := toAddrPointer(&v, ei.isptr, ei.deref)
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
b = append(b, 1<<3|WireEndGroup)
if !nerr.Merge(err) {
......@@ -2621,7 +2630,7 @@ func (u *marshalInfo) sizeV1Extensions(m map[int32]Extension) int {
ei := u.getExtElemInfo(e.desc)
v := e.value
p := toAddrPointer(&v, ei.isptr)
p := toAddrPointer(&v, ei.isptr, ei.deref)
n += ei.sizer(p, ei.tagsize)
}
return n
......@@ -2656,7 +2665,7 @@ func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, determ
ei := u.getExtElemInfo(e.desc)
v := e.value
p := toAddrPointer(&v, ei.isptr)
p := toAddrPointer(&v, ei.isptr, ei.deref)
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
if !nerr.Merge(err) {
return b, err
......
......@@ -136,7 +136,7 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
u.computeUnmarshalInfo()
}
if u.isMessageSet {
return UnmarshalMessageSet(b, m.offset(u.extensions).toExtensions())
return unmarshalMessageSet(b, m.offset(u.extensions).toExtensions())
}
var reqMask uint64 // bitmask of required fields we've seen.
var errLater error
......@@ -362,46 +362,48 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
}
// Find any types associated with oneof fields.
// TODO: XXX_OneofFuncs returns more info than we need. Get rid of some of it?
fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("XXX_OneofFuncs")
if fn.IsValid() {
res := fn.Call(nil)[3] // last return value from XXX_OneofFuncs: []interface{}
for i := res.Len() - 1; i >= 0; i-- {
v := res.Index(i) // interface{}
tptr := reflect.ValueOf(v.Interface()).Type() // *Msg_X
typ := tptr.Elem() // Msg_X
f := typ.Field(0) // oneof implementers have one field
baseUnmarshal := fieldUnmarshaler(&f)
tags := strings.Split(f.Tag.Get("protobuf"), ",")
fieldNum, err := strconv.Atoi(tags[1])
if err != nil {
panic("protobuf tag field not an integer: " + tags[1])
}
var name string
for _, tag := range tags {
if strings.HasPrefix(tag, "name=") {
name = strings.TrimPrefix(tag, "name=")
break
}
var oneofImplementers []interface{}
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
case oneofFuncsIface:
_, _, _, oneofImplementers = m.XXX_OneofFuncs()
case oneofWrappersIface:
oneofImplementers = m.XXX_OneofWrappers()
}
for _, v := range oneofImplementers {
tptr := reflect.TypeOf(v) // *Msg_X
typ := tptr.Elem() // Msg_X
f := typ.Field(0) // oneof implementers have one field
baseUnmarshal := fieldUnmarshaler(&f)
tags := strings.Split(f.Tag.Get("protobuf"), ",")
fieldNum, err := strconv.Atoi(tags[1])
if err != nil {
panic("protobuf tag field not an integer: " + tags[1])
}
var name string
for _, tag := range tags {
if strings.HasPrefix(tag, "name=") {
name = strings.TrimPrefix(tag, "name=")
break
}
}
// Find the oneof field that this struct implements.
// Might take O(n^2) to process all of the oneofs, but who cares.
for _, of := range oneofFields {
if tptr.Implements(of.ityp) {
// We have found the corresponding interface for this struct.
// That lets us know where this struct should be stored
// when we encounter it during unmarshaling.
unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal)
u.setTag(fieldNum, of.field, unmarshal, 0, name)
}
// Find the oneof field that this struct implements.
// Might take O(n^2) to process all of the oneofs, but who cares.
for _, of := range oneofFields {
if tptr.Implements(of.ityp) {
// We have found the corresponding interface for this struct.
// That lets us know where this struct should be stored
// when we encounter it during unmarshaling.
unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal)
u.setTag(fieldNum, of.field, unmarshal, 0, name)
}
}
}
// Get extension ranges, if any.
fn = reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray")
fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray")
if fn.IsValid() {
if !u.extensions.IsValid() && !u.oldExtensions.IsValid() {
panic("a message with extensions, but no extensions field in " + t.Name())
......
......@@ -456,6 +456,8 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
return nil
}
var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
// writeAny writes an arbitrary field.
func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
v = reflect.Indirect(v)
......@@ -519,8 +521,8 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert
// mutating this value.
v = v.Addr()
}
if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
text, err := etm.MarshalText()
if v.Type().Implements(textMarshalerType) {
text, err := v.Interface().(encoding.TextMarshaler).MarshalText()
if err != nil {
return err
}
......
......@@ -428,6 +428,7 @@ const (
ColumnOptionCollate
ColumnOptionCheck
ColumnOptionColumnFormat
ColumnOptionStorage
)
var (
......@@ -525,6 +526,9 @@ func (n *ColumnOption) Restore(ctx *RestoreCtx) error {
case ColumnOptionColumnFormat:
ctx.WriteKeyWord("COLUMN_FORMAT ")
ctx.WriteKeyWord(n.StrValue)
case ColumnOptionStorage:
ctx.WriteKeyWord("STORAGE ")
ctx.WriteKeyWord(n.StrValue)
default:
return errors.New("An error occurred while splicing ColumnOption")
}
......
......@@ -1828,6 +1828,7 @@ const (
ShowOpenTables
ShowAnalyzeStatus
ShowRegions
ShowBuiltins
)
const (
......@@ -2018,6 +2019,8 @@ func (n *ShowStmt) Restore(ctx *RestoreCtx) error {
case ShowPrivileges:
ctx.WriteKeyWord("PRIVILEGES")
case ShowBuiltins:
ctx.WriteKeyWord("BUILTINS")
// ShowTargetFilterable
default:
switch n.Tp {
......
......@@ -333,6 +333,7 @@ type ExecuteStmt struct {
UsingVars []ExprNode
BinaryArgs interface{}
ExecID uint32
IdxInMulti int
}
// Restore implements Node interface.
......
......@@ -170,6 +170,7 @@ var tokenMap = map[string]int{
"BOTH": both,
"BTREE": btree,
"BUCKETS": buckets,
"BUILTINS": builtins,
"BY": by,
"BYTE": byteType,
"CANCEL": cancel,
......
......@@ -565,6 +565,7 @@ import (
/* The following tokens belong to TiDBKeyword. Notice: make sure these tokens are contained in TiDBKeyword. */
admin "ADMIN"
buckets "BUCKETS"
builtins "BUILTINS"
cancel "CANCEL"
cmSketch "CMSKETCH"
ddl "DDL"
......@@ -1128,6 +1129,7 @@ import (
logOr "logical or operator"
LinearOpt "linear or empty"
FieldsOrColumns "Fields or columns"
StorageMedia "{DISK|MEMORY|DEFAULT}"
%type <ident>
ODBCDateTimeType "ODBC type keywords for date and time literals"
......@@ -2402,6 +2404,15 @@ ColumnOption:
{
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionColumnFormat, StrValue: $2.(string)}
}
| "STORAGE" StorageMedia
{
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionStorage, StrValue: $2}
yylex.AppendError(yylex.Errorf("The STORAGE clause is parsed but ignored by all storage engines."))
parser.lastErrorAsWarn()
}
StorageMedia:
"DEFAULT" | "DISK" | "MEMORY"
ColumnFormat:
"DEFAULT"
......@@ -4355,7 +4366,7 @@ UnReservedKeyword:
| "SQL_TSI_DAY" | "SQL_TSI_HOUR" | "SQL_TSI_MINUTE" | "SQL_TSI_MONTH" | "SQL_TSI_QUARTER" | "SQL_TSI_SECOND" | "SQL_TSI_WEEK" | "SQL_TSI_YEAR" | "INVISIBLE" | "VISIBLE" | "TYPE"
TiDBKeyword:
"ADMIN" | "AGG_TO_COP" |"BUCKETS" | "CANCEL" | "CMSKETCH" | "DDL" | "DEPTH" | "DRAINER" | "JOBS" | "JOB" | "NODE_ID" | "NODE_STATE" | "PUMP" | "SAMPLES" | "STATS" | "STATS_META" | "STATS_HISTOGRAMS" | "STATS_BUCKETS" | "STATS_HEALTHY" | "TIDB"
"ADMIN" | "AGG_TO_COP" |"BUCKETS" | "BUILTINS" | "CANCEL" | "CMSKETCH" | "DDL" | "DEPTH" | "DRAINER" | "JOBS" | "JOB" | "NODE_ID" | "NODE_STATE" | "PUMP" | "SAMPLES" | "STATS" | "STATS_META" | "STATS_HISTOGRAMS" | "STATS_BUCKETS" | "STATS_HEALTHY" | "TIDB"
| "HASH_JOIN" | "SM_JOIN" | "INL_JOIN" | "HASH_AGG" | "STREAM_AGG" | "USE_INDEX" | "IGNORE_INDEX" | "USE_INDEX_MERGE" | "NO_INDEX_MERGE" | "USE_TOJA" | "ENABLE_PLAN_CACHE" | "USE_PLAN_CACHE"
| "READ_CONSISTENT_REPLICA" | "READ_FROM_STORAGE" | "QB_NAME" | "QUERY_TYPE" | "MEMORY_QUOTA" | "OLAP" | "OLTP" | "TOPN" | "TIKV" | "TIFLASH" | "SPLIT" | "OPTIMISTIC" | "PESSIMISTIC" | "WIDTH" | "REGIONS"
......@@ -7872,6 +7883,12 @@ ShowStmt:
}
$$ = stmt
}
| "SHOW" "BUILTINS"
{
$$ = &ast.ShowStmt{
Tp: ast.ShowBuiltins,
}
}
ShowProfileTypesOpt:
{
......@@ -8832,6 +8849,10 @@ FixedPointType:
{
$$ = mysql.TypeNewDecimal
}
| "FIXED"
{
$$ = mysql.TypeNewDecimal
}
FloatingPointType:
"FLOAT"
......
......@@ -100,7 +100,7 @@ type Parser struct {
// the following fields are used by yyParse to reduce allocation.
cache []yySymType
yylval yySymType
yyVAL yySymType
yyVAL *yySymType
}
type stmtTexter interface {
......
......@@ -135,7 +135,8 @@ type StatementContext struct {
normalized string
digest string
}
Tables []TableEntry
Tables []TableEntry
PointExec bool // for point update cached execution, Constant expression need to set "paramMarker"
}
// StmtHints are SessionVars related sql hints.
......
......@@ -1258,12 +1258,16 @@ func (d *Datum) convertToMysqlBit(sc *stmtctx.StatementContext, target *FieldTyp
switch d.k {
case KindString, KindBytes:
uintValue, err = BinaryLiteral(d.b).ToInt(sc)
case KindInt64:
// if input kind is int64 (signed), when trans to bit, we need to treat it as unsigned
d.k = KindUint64
fallthrough
default:
uintDatum, err1 := d.convertToUint(sc, target)
uintValue, err = uintDatum.GetUint64(), err1
}
if target.Flen < 64 && uintValue >= 1<<(uint64(target.Flen)) {
return Datum{}, errors.Trace(ErrOverflow.GenWithStackByArgs("BIT", fmt.Sprintf("(%d)", target.Flen)))
return Datum{}, errors.Trace(ErrDataTooLong.GenWithStack("Data Too Long, field len %d", target.Flen))
}
byteSize := (target.Flen + 7) >> 3
ret.SetMysqlBit(NewBinaryLiteralFromUint(uintValue, byteSize))
......
......@@ -16,6 +16,7 @@ package types
import (
"fmt"
"math"
"time"
"github.com/pingcap/errors"
)
......@@ -38,6 +39,16 @@ func AddInt64(a int64, b int64) (int64, error) {
return a + b, nil
}
// AddDuration adds time.Duration a and b if no overflow, otherwise returns error.
func AddDuration(a time.Duration, b time.Duration) (time.Duration, error) {
if (a > 0 && b > 0 && math.MaxInt64-a < b) ||
(a < 0 && b < 0 && math.MinInt64-a > b) {
return 0, ErrOverflow.GenWithStackByArgs("BIGINT", fmt.Sprintf("(%d, %d)", int64(a), int64(b)))
}
return a + b, nil
}
// AddInteger adds uint64 a and int64 b and returns uint64 if no overflow error.
func AddInteger(a uint64, b int64) (uint64, error) {
if b >= 0 {
......
......@@ -292,8 +292,17 @@ const dateFormat = "%Y%m%d"
// 2012-12-12T10:10:10 -> 20121212101010
// 2012-12-12T10:10:10.123456 -> 20121212101010.123456
func (t Time) ToNumber() *MyDecimal {
dec := new(MyDecimal)
t.FillNumber(dec)
return dec
}
// FillNumber is the same as ToNumber,
// but reuses input decimal instead of allocating one.
func (t Time) FillNumber(dec *MyDecimal) {
if t.IsZero() {
return &MyDecimal{}
dec.FromInt(0)
return
}
// Fix issue #1046
......@@ -314,12 +323,9 @@ func (t Time) ToNumber() *MyDecimal {
s1 := fmt.Sprintf("%s.%06d", s, t.Time.Microsecond())
s = s1[:len(s)+int(t.Fsp)+1]
}
// We skip checking error here because time formatted string can be parsed certainly.
dec := new(MyDecimal)
err = dec.FromString([]byte(s))
terror.Log(errors.Trace(err))
return dec
}
// Convert converts t with type tp.
......
......@@ -32,6 +32,9 @@ type ActionOnExceed interface {
// SetLogHook binds a log hook which will be triggered and log an detailed
// message for the out-of-memory sql.
SetLogHook(hook func(uint64))
// SetFallback sets a fallback action which will be triggered if itself has
// already been triggered.
SetFallback(a ActionOnExceed)
}
// LogOnExceed logs a warning only once when memory usage exceeds memory quota.
......@@ -62,6 +65,9 @@ func (a *LogOnExceed) Action(t *Tracker) {
}
}
// SetFallback sets a fallback action.
func (a *LogOnExceed) SetFallback(ActionOnExceed) {}
// PanicOnExceed panics when memory usage exceeds memory quota.
type PanicOnExceed struct {
mutex sync.Mutex // For synchronization.
......@@ -90,6 +96,9 @@ func (a *PanicOnExceed) Action(t *Tracker) {
panic(PanicMemoryExceed + fmt.Sprintf("[conn_id=%d]", a.ConnID))
}
// SetFallback sets a fallback action.
func (a *PanicOnExceed) SetFallback(ActionOnExceed) {}
var (
errMemExceedThreshold = terror.ClassExecutor.New(codeMemExceedThreshold, mysql.MySQLErrName[mysql.ErrMemExceedThreshold])
)
......
......@@ -42,24 +42,28 @@ type Tracker struct {
sync.Mutex
children []*Tracker // The children memory trackers
}
actionMu struct {
sync.Mutex
actionOnExceed ActionOnExceed
}
label fmt.Stringer // Label of this "Tracker".
bytesConsumed int64 // Consumed bytes.
bytesLimit int64 // Negative value means no limit.
maxConsumed int64 // max number of bytes consumed during execution.
actionOnExceed ActionOnExceed
parent *Tracker // The parent memory tracker.
label fmt.Stringer // Label of this "Tracker".
bytesConsumed int64 // Consumed bytes.
bytesLimit int64 // bytesLimit <= 0 means no limit.
maxConsumed int64 // max number of bytes consumed during execution.
parent *Tracker // The parent memory tracker.
}
// NewTracker creates a memory tracker.
// 1. "label" is the label used in the usage string.
// 2. "bytesLimit <= 0" means no limit.
func NewTracker(label fmt.Stringer, bytesLimit int64) *Tracker {
return &Tracker{
label: label,
bytesLimit: bytesLimit,
actionOnExceed: &LogOnExceed{},
t := &Tracker{
label: label,
bytesLimit: bytesLimit,
}
t.actionMu.actionOnExceed = &LogOnExceed{}
return t
}
// CheckBytesLimit check whether the bytes limit of the tracker is equal to a value.
......@@ -76,7 +80,18 @@ func (t *Tracker) SetBytesLimit(bytesLimit int64) {
// SetActionOnExceed sets the action when memory usage exceeds bytesLimit.
func (t *Tracker) SetActionOnExceed(a ActionOnExceed) {
t.actionOnExceed = a
t.actionMu.Lock()
t.actionMu.actionOnExceed = a
t.actionMu.Unlock()
}
// FallbackOldAndSetNewAction sets the action when memory usage exceeds bytesLimit
// and set the original action as its fallback.
func (t *Tracker) FallbackOldAndSetNewAction(a ActionOnExceed) {
t.actionMu.Lock()
defer t.actionMu.Unlock()
a.SetFallback(t.actionMu.actionOnExceed)
t.actionMu.actionOnExceed = a
}
// SetLabel sets the label of a Tracker.
......@@ -151,12 +166,10 @@ func (t *Tracker) ReplaceChild(oldChild, newChild *Tracker) {
// which means this is a memory release operation. When memory usage of a tracker
// exceeds its bytesLimit, the tracker calls its action, so does each of its ancestors.
func (t *Tracker) Consume(bytes int64) {
var rootExceed *Tracker
for tracker := t; tracker != nil; tracker = tracker.parent {
if atomic.AddInt64(&tracker.bytesConsumed, bytes) >= tracker.bytesLimit && tracker.bytesLimit > 0 {
// TODO(fengliyuan): try to find a way to avoid logging at each tracker in chain.
if tracker.actionOnExceed != nil {
tracker.actionOnExceed.Action(tracker)
}
rootExceed = tracker
}
for {
......@@ -168,6 +181,13 @@ func (t *Tracker) Consume(bytes int64) {
break
}
}
if rootExceed != nil {
rootExceed.actionMu.Lock()
defer rootExceed.actionMu.Unlock()
if rootExceed.actionMu.actionOnExceed != nil {
rootExceed.actionMu.actionOnExceed.Action(rootExceed)
}
}
}
// BytesConsumed returns the consumed memory usage value in bytes.
......
......@@ -57,10 +57,10 @@
"revisionTime": "2016-01-25T20:49:56Z"
},
{
"checksumSHA1": "GaJLoEuMGnP5ofXvuweAI4wx06U=",
"checksumSHA1": "C8nYObwbo2oyODQbIT83lY37ajM=",
"path": "github.com/golang/protobuf/proto",
"revision": "ddf22928ea3c56eb4292a0adbbf5001b1e8e7d0d",
"revisionTime": "2018-10-05T18:17:28Z"
"revision": "1680a479a2cfb3fa22b972af7e36d0a0fde47bf8",
"revisionTime": "2019-09-20T23:43:18Z"
},
{
"checksumSHA1": "tkJPssYejSjuAwE2tdEnoEIj93Q=",
......@@ -129,118 +129,118 @@
"revisionTime": "2019-03-07T07:54:52Z"
},
{
"checksumSHA1": "6Q3DjwHqeCoRIxBT+Jy5ctnK6hw=",
"checksumSHA1": "QR1zSwFP8BdkTjNFC+/5gTS8C6c=",
"path": "github.com/pingcap/parser",
"revision": "33636bc5e5d6c114f4b443dee71ff72645656d96",
"revisionTime": "2019-09-23T03:17:04Z"
"revision": "51a2e3b2e34b61a7519e7d3e17dac38f0e8684f7",
"revisionTime": "2019-10-08T03:21:57Z"
},
{
"checksumSHA1": "2zFL4KJXdxL9LvQ/HNQhUDNIMd4=",
"checksumSHA1": "I4zlpjlOMFiWnRtAoSj50RSHsvk=",
"path": "github.com/pingcap/parser/ast",
"revision": "33636bc5e5d6c114f4b443dee71ff72645656d96",
"revisionTime": "2019-09-23T03:17:04Z"
"revision": "51a2e3b2e34b61a7519e7d3e17dac38f0e8684f7",
"revisionTime": "2019-10-08T03:21:57Z"
},
{
"checksumSHA1": "xiv40YqnvHcbIhaEzJqjh5K7ehM=",
"path": "github.com/pingcap/parser/auth",
"revision": "33636bc5e5d6c114f4b443dee71ff72645656d96",
"revisionTime": "2019-09-23T03:17:04Z"
"revision": "51a2e3b2e34b61a7519e7d3e17dac38f0e8684f7",
"revisionTime": "2019-10-08T03:21:57Z"
},
{
"checksumSHA1": "EvDXpplklIXmKqLclzWzaN/uHKQ=",
"path": "github.com/pingcap/parser/charset",
"revision": "33636bc5e5d6c114f4b443dee71ff72645656d96",
"revisionTime": "2019-09-23T03:17:04Z"
"revision": "51a2e3b2e34b61a7519e7d3e17dac38f0e8684f7",
"revisionTime": "2019-10-08T03:21:57Z"
},
{
"checksumSHA1": "Aao6Mul/qqogOwPwM2arBKZkYZs=",
"path": "github.com/pingcap/parser/format",
"revision": "33636bc5e5d6c114f4b443dee71ff72645656d96",
"revisionTime": "2019-09-23T03:17:04Z"
"revision": "51a2e3b2e34b61a7519e7d3e17dac38f0e8684f7",
"revisionTime": "2019-10-08T03:21:57Z"
},
{
"checksumSHA1": "GAJ7IUg0t8DCKJbJQxJLkklEj2E=",
"path": "github.com/pingcap/parser/model",
"revision": "33636bc5e5d6c114f4b443dee71ff72645656d96",
"revisionTime": "2019-09-23T03:17:04Z"
"revision": "51a2e3b2e34b61a7519e7d3e17dac38f0e8684f7",
"revisionTime": "2019-10-08T03:21:57Z"
},
{
"checksumSHA1": "pN8v8r1syhLlLXw9TOq6bFgJfnY=",
"path": "github.com/pingcap/parser/mysql",
"revision": "33636bc5e5d6c114f4b443dee71ff72645656d96",
"revisionTime": "2019-09-23T03:17:04Z"
"revision": "51a2e3b2e34b61a7519e7d3e17dac38f0e8684f7",
"revisionTime": "2019-10-08T03:21:57Z"
},
{
"checksumSHA1": "olapD16WCMBU9vrA5PtlERGFfXw=",
"path": "github.com/pingcap/parser/opcode",
"revision": "33636bc5e5d6c114f4b443dee71ff72645656d96",
"revisionTime": "2019-09-23T03:17:04Z"
"revision": "51a2e3b2e34b61a7519e7d3e17dac38f0e8684f7",
"revisionTime": "2019-10-08T03:21:57Z"
},
{
"checksumSHA1": "L6rzy3sJU1RPf7AkJN+0zcwW/YY=",
"path": "github.com/pingcap/parser/terror",
"revision": "33636bc5e5d6c114f4b443dee71ff72645656d96",
"revisionTime": "2019-09-23T03:17:04Z"
"revision": "51a2e3b2e34b61a7519e7d3e17dac38f0e8684f7",
"revisionTime": "2019-10-08T03:21:57Z"
},
{
"checksumSHA1": "u1Lmm4Fa3su4ElZMN4w0hPzFZl4=",
"path": "github.com/pingcap/parser/types",
"revision": "33636bc5e5d6c114f4b443dee71ff72645656d96",
"revisionTime": "2019-09-23T03:17:04Z"
"revision": "51a2e3b2e34b61a7519e7d3e17dac38f0e8684f7",
"revisionTime": "2019-10-08T03:21:57Z"
},
{
"checksumSHA1": "MqOvmeZKNG2g9yh3KS7WR18zhnM=",
"checksumSHA1": "guCKXZsHObqyjp6P2BwLSUpcG+Y=",
"path": "github.com/pingcap/tidb/sessionctx/stmtctx",
"revision": "582076b5cc9e0743bdd4aa95fbfd2ca1cc0e86e0",
"revisionTime": "2019-09-23T07:09:15Z"
"revision": "7c776be85d4445edd894052cc7585c310be6fca6",
"revisionTime": "2019-10-08T05:59:24Z"
},
{
"checksumSHA1": "E3tVZMdsoBoN+PbIBTd0hqxsHXA=",
"checksumSHA1": "DIDA04qsKrAzuwlq+uJrY3wTU2Y=",
"path": "github.com/pingcap/tidb/types",
"revision": "582076b5cc9e0743bdd4aa95fbfd2ca1cc0e86e0",
"revisionTime": "2019-09-23T07:09:15Z"
"revision": "7c776be85d4445edd894052cc7585c310be6fca6",
"revisionTime": "2019-10-08T05:59:24Z"
},
{
"checksumSHA1": "OSOQVeP518zWu3RoYSDWoh7DIjg=",
"path": "github.com/pingcap/tidb/types/json",
"revision": "582076b5cc9e0743bdd4aa95fbfd2ca1cc0e86e0",
"revisionTime": "2019-09-23T07:09:15Z"
"revision": "7c776be85d4445edd894052cc7585c310be6fca6",
"revisionTime": "2019-10-08T05:59:24Z"
},
{
"checksumSHA1": "45zWX5Q6D6aTEWtc4p/lbD9WD4o=",
"path": "github.com/pingcap/tidb/types/parser_driver",
"revision": "582076b5cc9e0743bdd4aa95fbfd2ca1cc0e86e0",
"revisionTime": "2019-09-23T07:09:15Z"
"revision": "7c776be85d4445edd894052cc7585c310be6fca6",
"revisionTime": "2019-10-08T05:59:24Z"
},
{
"checksumSHA1": "oCrNchmOGNQTnrkjk5CxFZpu2rE=",
"path": "github.com/pingcap/tidb/util/execdetails",
"revision": "582076b5cc9e0743bdd4aa95fbfd2ca1cc0e86e0",
"revisionTime": "2019-09-23T07:09:15Z"
"revision": "7c776be85d4445edd894052cc7585c310be6fca6",
"revisionTime": "2019-10-08T05:59:24Z"
},
{
"checksumSHA1": "QGCTegCx13wJyB0isXsV7mNIljE=",
"path": "github.com/pingcap/tidb/util/hack",
"revision": "582076b5cc9e0743bdd4aa95fbfd2ca1cc0e86e0",
"revisionTime": "2019-09-23T07:09:15Z"
"revision": "7c776be85d4445edd894052cc7585c310be6fca6",
"revisionTime": "2019-10-08T05:59:24Z"
},
{
"checksumSHA1": "SZhLPQR66Rd4kWkva6W3sJmSNLY=",
"path": "github.com/pingcap/tidb/util/logutil",
"revision": "582076b5cc9e0743bdd4aa95fbfd2ca1cc0e86e0",
"revisionTime": "2019-09-23T07:09:15Z"
"revision": "7c776be85d4445edd894052cc7585c310be6fca6",
"revisionTime": "2019-10-08T05:59:24Z"
},
{
"checksumSHA1": "OveQu0ABBJmMEwmmthqSRQC2Ef0=",
"path": "github.com/pingcap/tidb/util/math",
"revision": "582076b5cc9e0743bdd4aa95fbfd2ca1cc0e86e0",
"revisionTime": "2019-09-23T07:09:15Z"
"revision": "7c776be85d4445edd894052cc7585c310be6fca6",
"revisionTime": "2019-10-08T05:59:24Z"
},
{
"checksumSHA1": "wtzRvG5v1M4goFuWvP8ohkcZaT0=",
"checksumSHA1": "EhvViFDlyohEB9dvepvISTP28Zg=",
"path": "github.com/pingcap/tidb/util/memory",
"revision": "582076b5cc9e0743bdd4aa95fbfd2ca1cc0e86e0",
"revisionTime": "2019-09-23T07:09:15Z"
"revision": "7c776be85d4445edd894052cc7585c310be6fca6",
"revisionTime": "2019-10-08T05:59:24Z"
},
{
"checksumSHA1": "QPIBwDNUFF5Whrnd41S3mkKa4gQ=",
......@@ -497,68 +497,74 @@
{
"checksumSHA1": "aKn1oKcY74N8TRLm3Ayt7Q4bbI4=",
"path": "vitess.io/vitess/go/bytes2",
"revision": "909d0c8861b2b1a4a5942f99e7b44bf38e5db503",
"revisionTime": "2019-09-23T01:36:26Z"
"revision": "2c8664c8005b440c11fd070d30357c90f749f140",
"revisionTime": "2019-10-07T23:18:38Z"
},
{
"checksumSHA1": "bhE6CGQgZTIgLPp9lnvlKW/47xc=",
"path": "vitess.io/vitess/go/hack",
"revision": "909d0c8861b2b1a4a5942f99e7b44bf38e5db503",
"revisionTime": "2019-09-23T01:36:26Z"
"revision": "2c8664c8005b440c11fd070d30357c90f749f140",
"revisionTime": "2019-10-07T23:18:38Z"
},
{
"checksumSHA1": "IpNRu9mF+hsO3XRHzhW2Tz4G81o=",
"checksumSHA1": "v2dgco7U/RQtQbdX9ULGEXsZw6k=",
"path": "vitess.io/vitess/go/sqltypes",
"revision": "909d0c8861b2b1a4a5942f99e7b44bf38e5db503",
"revisionTime": "2019-09-23T01:36:26Z"
"revision": "2c8664c8005b440c11fd070d30357c90f749f140",
"revisionTime": "2019-10-07T23:18:38Z"
},
{
"checksumSHA1": "vAIRxI6MHsq3x1hLQwIyw5AvqtI=",
"path": "vitess.io/vitess/go/vt/log",
"revision": "909d0c8861b2b1a4a5942f99e7b44bf38e5db503",
"revisionTime": "2019-09-23T01:36:26Z"
"revision": "2c8664c8005b440c11fd070d30357c90f749f140",
"revisionTime": "2019-10-07T23:18:38Z"
},
{
"checksumSHA1": "//MHnGEq9xApvIMdwQaRrQf5ZWo=",
"checksumSHA1": "pm6qqJ+px6ev0huIVSE73XKT/pM=",
"path": "vitess.io/vitess/go/vt/proto/binlogdata",
"revision": "909d0c8861b2b1a4a5942f99e7b44bf38e5db503",
"revisionTime": "2019-09-23T01:36:26Z"
"revision": "2c8664c8005b440c11fd070d30357c90f749f140",
"revisionTime": "2019-10-07T23:18:38Z"
},
{
"checksumSHA1": "u8uuZWMqaXgQ1MduggrgIHU50FI=",
"checksumSHA1": "U2N66XbwVN2UbS7mI2fQqODKTFU=",
"path": "vitess.io/vitess/go/vt/proto/query",
"revision": "909d0c8861b2b1a4a5942f99e7b44bf38e5db503",
"revisionTime": "2019-09-23T01:36:26Z"
"revision": "2c8664c8005b440c11fd070d30357c90f749f140",
"revisionTime": "2019-10-07T23:18:38Z"
},
{
"checksumSHA1": "rJ1Iqz/lvaKikIUx4oEFfYJtoBQ=",
"checksumSHA1": "mioM1BFNP3voMMt6rvT6i9BMxTA=",
"path": "vitess.io/vitess/go/vt/proto/topodata",
"revision": "909d0c8861b2b1a4a5942f99e7b44bf38e5db503",
"revisionTime": "2019-09-23T01:36:26Z"
"revision": "2c8664c8005b440c11fd070d30357c90f749f140",
"revisionTime": "2019-10-07T23:18:38Z"
},
{
"checksumSHA1": "Bv8lucvoH9AnJSYiWX8MIrJl4zY=",
"checksumSHA1": "vFv/sVYQzHQFzLdxfLA3vX5Nz0U=",
"path": "vitess.io/vitess/go/vt/proto/vtgate",
"revision": "909d0c8861b2b1a4a5942f99e7b44bf38e5db503",
"revisionTime": "2019-09-23T01:36:26Z"
"revision": "2c8664c8005b440c11fd070d30357c90f749f140",
"revisionTime": "2019-10-07T23:18:38Z"
},
{
"checksumSHA1": "HeUJu5njPq9iznpAOcrLpLD7f9w=",
"checksumSHA1": "6Pzimtq+Jv8CI6kTqkAjMkPoZZI=",
"path": "vitess.io/vitess/go/vt/proto/vtrpc",
"revision": "909d0c8861b2b1a4a5942f99e7b44bf38e5db503",
"revisionTime": "2019-09-23T01:36:26Z"
"revision": "2c8664c8005b440c11fd070d30357c90f749f140",
"revisionTime": "2019-10-07T23:18:38Z"
},
{
"checksumSHA1": "IpnM59xLwj3/Kv5sbEFXBUvcj0o=",
"path": "vitess.io/vitess/go/vt/proto/vttime",
"revision": "2c8664c8005b440c11fd070d30357c90f749f140",
"revisionTime": "2019-10-07T23:18:38Z"
},
{
"checksumSHA1": "QP+KJhlTW4o4uRt2uFFiI9tjriI=",
"checksumSHA1": "W6ID/pp1kmcssaxW+PtAD3flg5E=",
"path": "vitess.io/vitess/go/vt/sqlparser",
"revision": "909d0c8861b2b1a4a5942f99e7b44bf38e5db503",
"revisionTime": "2019-09-23T01:36:26Z"
"revision": "2c8664c8005b440c11fd070d30357c90f749f140",
"revisionTime": "2019-10-07T23:18:38Z"
},
{
"checksumSHA1": "z9+F/lA1Xrl5S16LKssUH8VL6hs=",
"path": "vitess.io/vitess/go/vt/vterrors",
"revision": "909d0c8861b2b1a4a5942f99e7b44bf38e5db503",
"revisionTime": "2019-09-23T01:36:26Z"
"revision": "2c8664c8005b440c11fd070d30357c90f749f140",
"revisionTime": "2019-10-07T23:18:38Z"
}
],
"rootPath": "github.com/XiaoMi/soar"
......
......@@ -87,6 +87,28 @@ func Subtract(v1, v2 Value) (Value, error) {
return castFromNumeric(lresult, lresult.typ), nil
}
// Multiply takes two values and multiplies it together
func Multiply(v1, v2 Value) (Value, error) {
if v1.IsNull() || v2.IsNull() {
return NULL, nil
}
lv1, err := newNumeric(v1)
if err != nil {
return NULL, err
}
lv2, err := newNumeric(v2)
if err != nil {
return NULL, err
}
lresult, err := multiplyNumericWithError(lv1, lv2)
if err != nil {
return NULL, err
}
return castFromNumeric(lresult, lresult.typ), nil
}
// NullsafeAdd adds two Values in a null-safe manner. A null value
// is treated as 0. If both values are null, then a null is returned.
// If both values are not null, a numeric value is built
......@@ -430,6 +452,24 @@ func subtractNumericWithError(v1, v2 numeric) (numeric, error) {
panic("unreachable")
}
func multiplyNumericWithError(v1, v2 numeric) (numeric, error) {
v1, v2 = prioritize(v1, v2)
switch v1.typ {
case Int64:
return intTimesIntWithError(v1.ival, v2.ival)
case Uint64:
switch v2.typ {
case Int64:
return uintTimesIntWithError(v1.uval, v2.ival)
case Uint64:
return uintTimesUintWithError(v1.uval, v2.uval)
}
case Float64:
return floatTimesAny(v1.fval, v2), nil
}
panic("unreachable")
}
// prioritize reorders the input parameters
// to be Float64, Uint64, Int64.
func prioritize(v1, v2 numeric) (altv1, altv2 numeric) {
......@@ -477,6 +517,14 @@ func intMinusIntWithError(v1, v2 int64) (numeric, error) {
return numeric{typ: Int64, ival: result}, nil
}
func intTimesIntWithError(v1, v2 int64) (numeric, error) {
result := v1 * v2
if v1 != 0 && result/v1 != v2 {
return numeric{}, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "BIGINT value is out of range in %v * %v", v1, v2)
}
return numeric{typ: Int64, ival: result}, nil
}
func intMinusUintWithError(v1 int64, v2 uint64) (numeric, error) {
if v1 < 0 || v1 < int64(v2) {
return numeric{}, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "BIGINT UNSIGNED value is out of range in %v - %v", v1, v2)
......@@ -508,6 +556,13 @@ func uintMinusIntWithError(v1 uint64, v2 int64) (numeric, error) {
return uintMinusUintWithError(v1, uint64(v2))
}
func uintTimesIntWithError(v1 uint64, v2 int64) (numeric, error) {
if v2 < 0 || int64(v1) < 0 {
return numeric{}, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "BIGINT UNSIGNED value is out of range in %v * %v", v1, v2)
}
return uintTimesUintWithError(v1, uint64(v2))
}
func uintPlusUint(v1, v2 uint64) numeric {
result := v1 + v2
if result < v2 {
......@@ -529,6 +584,15 @@ func uintMinusUintWithError(v1, v2 uint64) (numeric, error) {
if v2 > v1 {
return numeric{}, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "BIGINT UNSIGNED value is out of range in %v - %v", v1, v2)
}
return numeric{typ: Uint64, uval: result}, nil
}
func uintTimesUintWithError(v1, v2 uint64) (numeric, error) {
result := v1 * v2
if result < v2 || result < v1 {
return numeric{}, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "BIGINT UNSIGNED value is out of range in %v * %v", v1, v2)
}
return numeric{typ: Uint64, uval: result}, nil
}
......@@ -552,6 +616,16 @@ func floatMinusAny(v1 float64, v2 numeric) numeric {
return numeric{typ: Float64, fval: v1 - v2.fval}
}
func floatTimesAny(v1 float64, v2 numeric) numeric {
switch v2.typ {
case Int64:
v2.fval = float64(v2.ival)
case Uint64:
v2.fval = float64(v2.uval)
}
return numeric{typ: Float64, fval: v1 * v2.fval}
}
func anyMinusFloat(v1 numeric, v2 float64) numeric {
switch v1.typ {
case Int64:
......
......@@ -154,6 +154,7 @@ const (
// If you add to this map, make sure you add a test case
// in tabletserver/endtoend.
var mysqlToType = map[int64]querypb.Type{
0: Decimal,
1: Int8,
2: Int16,
3: Int32,
......@@ -169,8 +170,13 @@ var mysqlToType = map[int64]querypb.Type{
13: Year,
15: VarChar,
16: Bit,
17: Timestamp,
18: Datetime,
19: Time,
245: TypeJSON,
246: Decimal,
247: Enum,
248: Set,
249: Text,
250: Text,
251: Text,
......@@ -245,6 +251,24 @@ func MySQLToType(mysqlType, flags int64) (typ querypb.Type, err error) {
return modifyType(result, flags), nil
}
//TypeEquivalenceCheck returns whether two types are equivalent.
func AreTypesEquivalent(mysqlTypeFromBinlog, mysqlTypeFromSchema querypb.Type) bool {
return (mysqlTypeFromBinlog == mysqlTypeFromSchema) ||
(mysqlTypeFromBinlog == VarChar && mysqlTypeFromSchema == VarBinary) ||
// Binlog only has base type. But doesn't have per-column-flags to differentiate
// various logical types. For Binary, Enum, Set types, binlog only returns Char
// as data type.
(mysqlTypeFromBinlog == Char && mysqlTypeFromSchema == Binary) ||
(mysqlTypeFromBinlog == Char && mysqlTypeFromSchema == Enum) ||
(mysqlTypeFromBinlog == Char && mysqlTypeFromSchema == Set) ||
(mysqlTypeFromBinlog == Text && mysqlTypeFromSchema == Blob) ||
(mysqlTypeFromBinlog == Int8 && mysqlTypeFromSchema == Uint8) ||
(mysqlTypeFromBinlog == Int16 && mysqlTypeFromSchema == Uint16) ||
(mysqlTypeFromBinlog == Int24 && mysqlTypeFromSchema == Uint24) ||
(mysqlTypeFromBinlog == Int32 && mysqlTypeFromSchema == Uint32) ||
(mysqlTypeFromBinlog == Int64 && mysqlTypeFromSchema == Uint64)
}
// typeToMySQL is the reverse of mysqlToType.
var typeToMySQL = map[querypb.Type]struct {
typ int64
......
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: vtrpc.proto
package vtrpc // import "vitess.io/vitess/go/vt/proto/vtrpc"
package vtrpc
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
......@@ -16,7 +18,7 @@ var _ = math.Inf
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// Code represents canonical error codes. The names, numbers and comments
// must match the ones defined by grpc:
......@@ -144,6 +146,7 @@ var Code_name = map[int32]string{
14: "UNAVAILABLE",
15: "DATA_LOSS",
}
var Code_value = map[string]int32{
"OK": 0,
"CANCELED": 1,
......@@ -167,8 +170,9 @@ var Code_value = map[string]int32{
func (x Code) String() string {
return proto.EnumName(Code_name, int32(x))
}
func (Code) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_vtrpc_88a14d8f1bc03cf5, []int{0}
return fileDescriptor_750b4cf641561858, []int{0}
}
// LegacyErrorCode is the enum values for Errors. This type is deprecated.
......@@ -256,6 +260,7 @@ var LegacyErrorCode_name = map[int32]string{
11: "TRANSIENT_ERROR_LEGACY",
12: "UNAUTHENTICATED_LEGACY",
}
var LegacyErrorCode_value = map[string]int32{
"SUCCESS_LEGACY": 0,
"CANCELLED_LEGACY": 1,
......@@ -275,8 +280,9 @@ var LegacyErrorCode_value = map[string]int32{
func (x LegacyErrorCode) String() string {
return proto.EnumName(LegacyErrorCode_name, int32(x))
}
func (LegacyErrorCode) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_vtrpc_88a14d8f1bc03cf5, []int{1}
return fileDescriptor_750b4cf641561858, []int{1}
}
// CallerID is passed along RPCs to identify the originating client
......@@ -311,16 +317,17 @@ func (m *CallerID) Reset() { *m = CallerID{} }
func (m *CallerID) String() string { return proto.CompactTextString(m) }
func (*CallerID) ProtoMessage() {}
func (*CallerID) Descriptor() ([]byte, []int) {
return fileDescriptor_vtrpc_88a14d8f1bc03cf5, []int{0}
return fileDescriptor_750b4cf641561858, []int{0}
}
func (m *CallerID) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CallerID.Unmarshal(m, b)
}
func (m *CallerID) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CallerID.Marshal(b, m, deterministic)
}
func (dst *CallerID) XXX_Merge(src proto.Message) {
xxx_messageInfo_CallerID.Merge(dst, src)
func (m *CallerID) XXX_Merge(src proto.Message) {
xxx_messageInfo_CallerID.Merge(m, src)
}
func (m *CallerID) XXX_Size() int {
return xxx_messageInfo_CallerID.Size(m)
......@@ -369,16 +376,17 @@ func (m *RPCError) Reset() { *m = RPCError{} }
func (m *RPCError) String() string { return proto.CompactTextString(m) }
func (*RPCError) ProtoMessage() {}
func (*RPCError) Descriptor() ([]byte, []int) {
return fileDescriptor_vtrpc_88a14d8f1bc03cf5, []int{1}
return fileDescriptor_750b4cf641561858, []int{1}
}
func (m *RPCError) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RPCError.Unmarshal(m, b)
}
func (m *RPCError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_RPCError.Marshal(b, m, deterministic)
}
func (dst *RPCError) XXX_Merge(src proto.Message) {
xxx_messageInfo_RPCError.Merge(dst, src)
func (m *RPCError) XXX_Merge(src proto.Message) {
xxx_messageInfo_RPCError.Merge(m, src)
}
func (m *RPCError) XXX_Size() int {
return xxx_messageInfo_RPCError.Size(m)
......@@ -411,15 +419,15 @@ func (m *RPCError) GetCode() Code {
}
func init() {
proto.RegisterType((*CallerID)(nil), "vtrpc.CallerID")
proto.RegisterType((*RPCError)(nil), "vtrpc.RPCError")
proto.RegisterEnum("vtrpc.Code", Code_name, Code_value)
proto.RegisterEnum("vtrpc.LegacyErrorCode", LegacyErrorCode_name, LegacyErrorCode_value)
proto.RegisterType((*CallerID)(nil), "vtrpc.CallerID")
proto.RegisterType((*RPCError)(nil), "vtrpc.RPCError")
}
func init() { proto.RegisterFile("vtrpc.proto", fileDescriptor_vtrpc_88a14d8f1bc03cf5) }
func init() { proto.RegisterFile("vtrpc.proto", fileDescriptor_750b4cf641561858) }
var fileDescriptor_vtrpc_88a14d8f1bc03cf5 = []byte{
var fileDescriptor_750b4cf641561858 = []byte{
// 605 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x93, 0x4d, 0x4f, 0x1b, 0x3b,
0x14, 0x86, 0xc9, 0x07, 0xf9, 0x38, 0x13, 0x88, 0x31, 0x5f, 0xe1, 0x5e, 0xae, 0xee, 0x55, 0x56,
......
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: time.proto
package vttime
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// Time represents a time stamp in nanoseconds. In go, use logutil library
// to convert times.
type Time struct {
Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
Nanoseconds int32 `protobuf:"varint,2,opt,name=nanoseconds,proto3" json:"nanoseconds,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Time) Reset() { *m = Time{} }
func (m *Time) String() string { return proto.CompactTextString(m) }
func (*Time) ProtoMessage() {}
func (*Time) Descriptor() ([]byte, []int) {
return fileDescriptor_49a92d779a28c7fd, []int{0}
}
func (m *Time) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Time.Unmarshal(m, b)
}
func (m *Time) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Time.Marshal(b, m, deterministic)
}
func (m *Time) XXX_Merge(src proto.Message) {
xxx_messageInfo_Time.Merge(m, src)
}
func (m *Time) XXX_Size() int {
return xxx_messageInfo_Time.Size(m)
}
func (m *Time) XXX_DiscardUnknown() {
xxx_messageInfo_Time.DiscardUnknown(m)
}
var xxx_messageInfo_Time proto.InternalMessageInfo
func (m *Time) GetSeconds() int64 {
if m != nil {
return m.Seconds
}
return 0
}
func (m *Time) GetNanoseconds() int32 {
if m != nil {
return m.Nanoseconds
}
return 0
}
func init() {
proto.RegisterType((*Time)(nil), "vttime.Time")
}
func init() { proto.RegisterFile("time.proto", fileDescriptor_49a92d779a28c7fd) }
var fileDescriptor_49a92d779a28c7fd = []byte{
// 120 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0xc9, 0xcc, 0x4d,
0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2b, 0x2b, 0x01, 0xf1, 0x94, 0x9c, 0xb8, 0x58,
0x42, 0x32, 0x73, 0x53, 0x85, 0x24, 0xb8, 0xd8, 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25,
0x18, 0x15, 0x18, 0x35, 0x98, 0x83, 0x60, 0x5c, 0x21, 0x05, 0x2e, 0xee, 0xbc, 0xc4, 0xbc, 0x7c,
0x98, 0x2c, 0x93, 0x02, 0xa3, 0x06, 0x6b, 0x10, 0xb2, 0x90, 0x93, 0x6a, 0x94, 0x72, 0x59, 0x66,
0x49, 0x6a, 0x71, 0xb1, 0x5e, 0x66, 0xbe, 0x3e, 0x84, 0xa5, 0x9f, 0x9e, 0xaf, 0x5f, 0x56, 0xa2,
0x0f, 0xb6, 0x4b, 0x1f, 0x62, 0x55, 0x12, 0x1b, 0x98, 0x67, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff,
0xb4, 0x42, 0xf5, 0xf7, 0x87, 0x00, 0x00, 0x00,
}
......@@ -30,10 +30,13 @@ import (
vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
)
// StatementType encodes the type of a SQL statement
type StatementType int
// These constants are used to identify the SQL statement type.
// Changing this list will require reviewing all calls to Preview.
const (
StmtSelect = iota
StmtSelect StatementType = iota
StmtStream
StmtInsert
StmtReplace
......@@ -53,7 +56,7 @@ const (
// Preview analyzes the beginning of the query using a simpler and faster
// textual comparison to identify the statement type.
func Preview(sql string) int {
func Preview(sql string) StatementType {
trimmed := StripLeadingComments(sql)
if strings.Index(trimmed, "/*!") == 0 {
......@@ -111,9 +114,8 @@ func Preview(sql string) int {
return StmtUnknown
}
// StmtType returns the statement type as a string
func StmtType(stmtType int) string {
switch stmtType {
func (s StatementType) String() string {
switch s {
case StmtSelect:
return "SELECT"
case StmtStream:
......
......@@ -2007,7 +2007,7 @@ func (node TableName) walkSubtree(visit Visit) error {
// IsEmpty returns true if TableName is nil or empty.
func (node TableName) IsEmpty() bool {
// If Name is empty, Qualifer is also empty.
// If Name is empty, Qualifier is also empty.
return node.Name.IsEmpty()
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册