diff --git a/go/vt/proto/vtgate/vtgate.pb.go b/go/vt/proto/vtgate/vtgate.pb.go index c1055fbc30f..7b7370e8a07 100644 --- a/go/vt/proto/vtgate/vtgate.pb.go +++ b/go/vt/proto/vtgate/vtgate.pb.go @@ -143,10 +143,12 @@ type Session struct { // user_defined_variables contains all the @variables defined for this session UserDefinedVariables map[string]*query.BindVariable `protobuf:"bytes,13,rep,name=user_defined_variables,json=userDefinedVariables,proto3" json:"user_defined_variables,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // system_variables keeps track of all session variables set for this connection - SystemVariables map[string]string `protobuf:"bytes,14,rep,name=system_variables,json=systemVariables,proto3" json:"system_variables,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + SystemVariables map[string]string `protobuf:"bytes,14,rep,name=system_variables,json=systemVariables,proto3" json:"system_variables,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // row_count keeps track of the last seen rows affected for this session + RowCount int64 `protobuf:"varint,15,opt,name=row_count,json=rowCount,proto3" json:"row_count,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Session) Reset() { *m = Session{} } @@ -272,6 +274,13 @@ func (m *Session) GetSystemVariables() map[string]string { return nil } +func (m *Session) GetRowCount() int64 { + if m != nil { + return m.RowCount + } + return 0 +} + type Session_ShardSession struct { Target *query.Target `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` TransactionId int64 `protobuf:"varint,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` @@ -961,79 +970,78 @@ func init() { proto.RegisterType((*VStreamResponse)(nil), "vtgate.VStreamResponse") } -func init() { - proto.RegisterFile("vtgate.proto", fileDescriptor_aab96496ceaf1ebb) -} +func init() { proto.RegisterFile("vtgate.proto", fileDescriptor_aab96496ceaf1ebb) } var fileDescriptor_aab96496ceaf1ebb = []byte{ - // 1099 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xdd, 0x6e, 0x1b, 0x37, - 0x13, 0xcd, 0xea, 0x5f, 0xa3, 0xbf, 0xfd, 0x18, 0x25, 0xdf, 0x46, 0x4d, 0x0b, 0x41, 0x49, 0x10, - 0xc5, 0x2d, 0xa4, 0x42, 0x45, 0x8b, 0xa2, 0x68, 0x51, 0xd8, 0xb2, 0x12, 0xa8, 0xb0, 0x2d, 0x97, - 0x92, 0x6d, 0xa0, 0x48, 0xb1, 0x58, 0x6b, 0x69, 0x99, 0x88, 0xbc, 0xdc, 0x90, 0x94, 0x5c, 0x3d, - 0x45, 0xef, 0xfb, 0x02, 0x7d, 0x97, 0xde, 0xf5, 0x6d, 0x7a, 0x59, 0x90, 0x5c, 0x49, 0x6b, 0xd5, - 0x6d, 0x1c, 0x07, 0xbe, 0x59, 0x90, 0x73, 0x86, 0xc3, 0x99, 0x73, 0x38, 0xe4, 0x42, 0x71, 0x2e, - 0x27, 0x9e, 0x24, 0xad, 0x90, 0x33, 0xc9, 0x50, 0xc6, 0xcc, 0x6a, 0xf6, 0x29, 0x0d, 0xa6, 0x6c, - 0xe2, 0x7b, 0xd2, 0x33, 0x48, 0xad, 0xf0, 0x76, 0x46, 0xf8, 0x22, 0x9a, 0x94, 0x25, 0x0b, 0x59, - 0x1c, 0x9c, 0x4b, 0x1e, 0x8e, 0xcd, 0xa4, 0xf1, 0x57, 0x16, 0xb2, 0x43, 0x22, 0x04, 0x65, 0x01, - 0x7a, 0x06, 0x65, 0x1a, 0xb8, 0x92, 0x7b, 0x81, 0xf0, 0xc6, 0x92, 0xb2, 0xc0, 0xb1, 0xea, 0x56, - 0x33, 0x87, 0x4b, 0x34, 0x18, 0xad, 0x8d, 0xa8, 0x0b, 0x65, 0x71, 0xee, 0x71, 0xdf, 0x15, 0x66, - 0x9d, 0x70, 0x12, 0xf5, 0x64, 0xb3, 0xd0, 0x79, 0xdc, 0x8a, 0xb2, 0x8b, 0xe2, 0xb5, 0x86, 0xca, - 0x2b, 0x9a, 0xe0, 0x92, 0x88, 0xcd, 0x04, 0xfa, 0x08, 0xf2, 0x82, 0x06, 0x93, 0x29, 0x71, 0xfd, - 0x53, 0x27, 0xa9, 0xb7, 0xc9, 0x19, 0xc3, 0xee, 0x29, 0xfa, 0x04, 0xc0, 0x9b, 0x49, 0x36, 0x66, - 0x17, 0x17, 0x54, 0x3a, 0x29, 0x8d, 0xc6, 0x2c, 0xe8, 0x09, 0x94, 0xa4, 0xc7, 0x27, 0x44, 0xba, - 0x42, 0x72, 0x1a, 0x4c, 0x9c, 0x74, 0xdd, 0x6a, 0xe6, 0x71, 0xd1, 0x18, 0x87, 0xda, 0x86, 0xda, - 0x90, 0x65, 0xa1, 0xd4, 0xf9, 0x65, 0xea, 0x56, 0xb3, 0xd0, 0x79, 0xd0, 0x32, 0xac, 0xf4, 0x7e, - 0x21, 0xe3, 0x99, 0x24, 0x03, 0x03, 0xe2, 0xa5, 0x17, 0xda, 0x01, 0x3b, 0x56, 0xbb, 0x7b, 0xc1, - 0x7c, 0xe2, 0x64, 0xeb, 0x56, 0xb3, 0xdc, 0xf9, 0xff, 0xb2, 0xb2, 0x18, 0x0d, 0xfb, 0xcc, 0x27, - 0xb8, 0x22, 0xaf, 0x1a, 0x50, 0x1b, 0x72, 0x97, 0x1e, 0x0f, 0x68, 0x30, 0x11, 0x4e, 0x4e, 0xb3, - 0x72, 0x3f, 0xda, 0xf5, 0x47, 0xf5, 0x3d, 0x31, 0x18, 0x5e, 0x39, 0xa1, 0xef, 0xa1, 0x18, 0x72, - 0xb2, 0xa6, 0x32, 0x7f, 0x03, 0x2a, 0x0b, 0x21, 0x27, 0x2b, 0x22, 0xb7, 0xa1, 0x14, 0x32, 0x21, - 0xd7, 0x11, 0xe0, 0x06, 0x11, 0x8a, 0x6a, 0xc9, 0x2a, 0xc4, 0x53, 0x28, 0x4f, 0x3d, 0x21, 0x5d, - 0x1a, 0x08, 0xc2, 0xa5, 0x4b, 0x7d, 0xa7, 0x50, 0xb7, 0x9a, 0x29, 0x5c, 0x54, 0xd6, 0xbe, 0x36, - 0xf6, 0x7d, 0xf4, 0x31, 0xc0, 0x19, 0x9b, 0x05, 0xbe, 0xcb, 0xd9, 0xa5, 0x70, 0x8a, 0xda, 0x23, - 0xaf, 0x2d, 0x98, 0x5d, 0x0a, 0xe4, 0xc2, 0xc3, 0x99, 0x20, 0xdc, 0xf5, 0xc9, 0x19, 0x0d, 0x88, - 0xef, 0xce, 0x3d, 0x4e, 0xbd, 0xd3, 0x29, 0x11, 0x4e, 0x49, 0x27, 0xf4, 0x62, 0x33, 0xa1, 0x23, - 0x41, 0xf8, 0xae, 0x71, 0x3e, 0x5e, 0xfa, 0xf6, 0x02, 0xc9, 0x17, 0xb8, 0x3a, 0xbb, 0x06, 0x42, - 0x03, 0xb0, 0xc5, 0x42, 0x48, 0x72, 0x11, 0x0b, 0x5d, 0xd6, 0xa1, 0x9f, 0xfe, 0xa3, 0x56, 0xed, - 0xb7, 0x11, 0xb5, 0x22, 0xae, 0x5a, 0x6b, 0xaf, 0xa1, 0x18, 0x27, 0x05, 0x3d, 0x83, 0x8c, 0x39, - 0x40, 0xfa, 0xd8, 0x17, 0x3a, 0xa5, 0x48, 0xb9, 0x91, 0x36, 0xe2, 0x08, 0x54, 0x5d, 0x12, 0x3f, - 0x26, 0xd4, 0x77, 0x12, 0x75, 0xab, 0x99, 0xc4, 0xa5, 0x98, 0xb5, 0xef, 0xd7, 0x5e, 0xc3, 0xa3, - 0x7f, 0xad, 0x10, 0xd9, 0x90, 0x7c, 0x43, 0x16, 0x7a, 0x9f, 0x3c, 0x56, 0x43, 0xf4, 0x02, 0xd2, - 0x73, 0x6f, 0x3a, 0x23, 0x3a, 0xd8, 0xfa, 0xd4, 0xec, 0xd0, 0x60, 0xb5, 0x16, 0x1b, 0x8f, 0x6f, - 0x12, 0x5f, 0x5b, 0xb5, 0x1d, 0xa8, 0x5e, 0x57, 0xe4, 0x35, 0x81, 0xab, 0xf1, 0xc0, 0xf9, 0x58, - 0x8c, 0xc6, 0xef, 0x09, 0x28, 0x47, 0xbd, 0x80, 0xc9, 0xdb, 0x19, 0x11, 0x12, 0x7d, 0x06, 0xf9, - 0xb1, 0x37, 0x9d, 0x12, 0xae, 0xca, 0x32, 0x2c, 0x54, 0x5a, 0xe6, 0xba, 0xe8, 0x6a, 0x7b, 0x7f, - 0x17, 0xe7, 0x8c, 0x47, 0xdf, 0x47, 0x2f, 0x20, 0x1b, 0x9d, 0xba, 0x28, 0xeb, 0xca, 0x86, 0x10, - 0x78, 0x89, 0xa3, 0xe7, 0x90, 0xd6, 0x05, 0xe9, 0x56, 0x2f, 0x74, 0xfe, 0xb7, 0x2c, 0x4f, 0x1d, - 0x1f, 0xdd, 0x19, 0xd8, 0xe0, 0xe8, 0x4b, 0x28, 0x48, 0x55, 0x8f, 0x74, 0xe5, 0x22, 0x24, 0xba, - 0xf7, 0xcb, 0x9d, 0x6a, 0x6b, 0x75, 0x85, 0x8d, 0x34, 0x38, 0x5a, 0x84, 0x04, 0x83, 0x5c, 0x8d, - 0x95, 0x28, 0x6f, 0xc8, 0x42, 0x84, 0xde, 0x98, 0xb8, 0xfa, 0xa2, 0xd1, 0x3d, 0x9f, 0xc7, 0xa5, - 0xa5, 0x55, 0x2b, 0x1d, 0xbf, 0x13, 0xb2, 0x37, 0xb9, 0x13, 0x7e, 0x48, 0xe5, 0xd2, 0x76, 0xa6, - 0xf1, 0xab, 0x05, 0x95, 0x15, 0x53, 0x22, 0x64, 0x81, 0x50, 0x3b, 0xa6, 0x09, 0xe7, 0x8c, 0x6f, - 0xd0, 0x84, 0x0f, 0xbb, 0x3d, 0x65, 0xc6, 0x06, 0x7d, 0x1f, 0x8e, 0xb6, 0x20, 0xc3, 0x89, 0x98, - 0x4d, 0x65, 0x44, 0x12, 0x8a, 0xdf, 0x1c, 0x58, 0x23, 0x38, 0xf2, 0x68, 0xfc, 0x99, 0x80, 0xfb, - 0x51, 0x46, 0x3b, 0x9e, 0x1c, 0x9f, 0xdf, 0xb9, 0x80, 0x9f, 0x42, 0x56, 0x65, 0x43, 0x89, 0x70, - 0x92, 0xba, 0xe9, 0xae, 0x91, 0x70, 0xe9, 0xf1, 0x01, 0x22, 0x7a, 0xe2, 0xca, 0xfb, 0x93, 0x36, - 0xef, 0x8f, 0x27, 0xe2, 0xef, 0xcf, 0x1d, 0x69, 0xdd, 0xf8, 0xcd, 0x82, 0xea, 0x55, 0x4e, 0xef, - 0x4c, 0xea, 0xcf, 0x21, 0x6b, 0x84, 0x5c, 0xb2, 0xf9, 0x30, 0xca, 0xcd, 0xc8, 0x7c, 0x42, 0xe5, - 0xb9, 0x09, 0xbd, 0x74, 0x53, 0xcd, 0x5a, 0x1d, 0x4a, 0x4e, 0xbc, 0x8b, 0x0f, 0x6a, 0xd9, 0x55, - 0x1f, 0x26, 0xde, 0xaf, 0x0f, 0x93, 0xb7, 0xee, 0xc3, 0xd4, 0x3b, 0xb4, 0x49, 0xdf, 0xe8, 0x6d, - 0x8e, 0x71, 0x9b, 0xf9, 0x6f, 0x6e, 0x1b, 0x5d, 0x78, 0xb0, 0x41, 0x54, 0x24, 0xe3, 0xba, 0xbf, - 0xac, 0x77, 0xf6, 0xd7, 0xcf, 0xf0, 0x08, 0x13, 0xc1, 0xa6, 0x73, 0x12, 0x3b, 0x79, 0xb7, 0xa3, - 0x1c, 0x41, 0xca, 0x97, 0xd1, 0x2b, 0x91, 0xc7, 0x7a, 0xdc, 0x78, 0x0c, 0xb5, 0xeb, 0xc2, 0x9b, - 0x44, 0x1b, 0x7f, 0x58, 0x50, 0x3e, 0x36, 0x35, 0xdc, 0x6e, 0xcb, 0x0d, 0xf1, 0x12, 0x37, 0x14, - 0xef, 0x39, 0xa4, 0xe7, 0x13, 0x95, 0xea, 0xf2, 0x92, 0x8e, 0xfd, 0x57, 0x1e, 0xbf, 0x92, 0xd4, - 0xc7, 0x06, 0x57, 0x4c, 0x9e, 0xd1, 0xa9, 0x24, 0x5c, 0xab, 0xab, 0x98, 0x8c, 0x79, 0xbe, 0xd4, - 0x08, 0x8e, 0x3c, 0x1a, 0xdf, 0x41, 0x65, 0x55, 0xcb, 0x5a, 0x08, 0x32, 0x27, 0x81, 0x14, 0x8e, - 0xa5, 0x0f, 0xff, 0x95, 0xe5, 0xc7, 0x3d, 0x05, 0xe1, 0xc8, 0x63, 0x6b, 0x17, 0x2a, 0x1b, 0x3f, - 0x5d, 0xa8, 0x02, 0x85, 0xa3, 0x83, 0xe1, 0x61, 0xaf, 0xdb, 0x7f, 0xd9, 0xef, 0xed, 0xda, 0xf7, - 0x10, 0x40, 0x66, 0xd8, 0x3f, 0x78, 0xb5, 0xd7, 0xb3, 0x2d, 0x94, 0x87, 0xf4, 0xfe, 0xd1, 0xde, - 0xa8, 0x6f, 0x27, 0xd4, 0x70, 0x74, 0x32, 0x38, 0xec, 0xda, 0xc9, 0xad, 0x6f, 0xa1, 0xd0, 0xd5, - 0xbf, 0x8e, 0x03, 0xee, 0x13, 0xae, 0x16, 0x1c, 0x0c, 0xf0, 0xfe, 0xf6, 0x9e, 0x7d, 0x0f, 0x65, - 0x21, 0x79, 0x88, 0xd5, 0xca, 0x1c, 0xa4, 0x0e, 0x07, 0xc3, 0x91, 0x9d, 0x40, 0x65, 0x80, 0xed, - 0xa3, 0xd1, 0xa0, 0x3b, 0xd8, 0xdf, 0xef, 0x8f, 0xec, 0xe4, 0xce, 0x57, 0x50, 0xa1, 0xac, 0x35, - 0xa7, 0x92, 0x08, 0x61, 0x7e, 0x9b, 0x7f, 0x7a, 0x12, 0xcd, 0x28, 0x6b, 0x9b, 0x51, 0x7b, 0xc2, - 0xda, 0x73, 0xd9, 0xd6, 0x68, 0xdb, 0x1c, 0xcd, 0xd3, 0x8c, 0x9e, 0x7d, 0xf1, 0x77, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x3d, 0xd4, 0x72, 0x2b, 0xb6, 0x0b, 0x00, 0x00, + // 1117 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xdb, 0x6e, 0x1b, 0x37, + 0x13, 0xce, 0xea, 0xac, 0xd1, 0x69, 0x7f, 0x46, 0xc9, 0xbf, 0x51, 0xd3, 0x42, 0x50, 0x12, 0x44, + 0x71, 0x0b, 0xa9, 0x50, 0xd1, 0xa2, 0x28, 0x5a, 0x14, 0xb6, 0xac, 0x04, 0x2a, 0x6c, 0xcb, 0xa5, + 0x64, 0x1b, 0x28, 0x52, 0x2c, 0xd6, 0x5a, 0x5a, 0x26, 0x22, 0x2f, 0x37, 0x24, 0x25, 0x57, 0x4f, + 0xd1, 0xab, 0xde, 0xf4, 0x05, 0xfa, 0x2e, 0xbd, 0xeb, 0x1b, 0x15, 0x24, 0x57, 0xd2, 0x5a, 0x75, + 0x1b, 0xc7, 0x81, 0x6f, 0x16, 0xe4, 0xcc, 0x70, 0x38, 0xf3, 0x7d, 0x33, 0xc3, 0x85, 0xe2, 0x5c, + 0x4e, 0x3c, 0x49, 0x5a, 0x21, 0x67, 0x92, 0xa1, 0x8c, 0xd9, 0xd5, 0xec, 0x53, 0x1a, 0x4c, 0xd9, + 0xc4, 0xf7, 0xa4, 0x67, 0x34, 0xb5, 0xc2, 0xdb, 0x19, 0xe1, 0x8b, 0x68, 0x53, 0x96, 0x2c, 0x64, + 0x71, 0xe5, 0x5c, 0xf2, 0x70, 0x6c, 0x36, 0x8d, 0xdf, 0x72, 0x90, 0x1d, 0x12, 0x21, 0x28, 0x0b, + 0xd0, 0x33, 0x28, 0xd3, 0xc0, 0x95, 0xdc, 0x0b, 0x84, 0x37, 0x96, 0x94, 0x05, 0x8e, 0x55, 0xb7, + 0x9a, 0x39, 0x5c, 0xa2, 0xc1, 0x68, 0x2d, 0x44, 0x5d, 0x28, 0x8b, 0x73, 0x8f, 0xfb, 0xae, 0x30, + 0xe7, 0x84, 0x93, 0xa8, 0x27, 0x9b, 0x85, 0xce, 0xe3, 0x56, 0x14, 0x5d, 0xe4, 0xaf, 0x35, 0x54, + 0x56, 0xd1, 0x06, 0x97, 0x44, 0x6c, 0x27, 0xd0, 0x47, 0x90, 0x17, 0x34, 0x98, 0x4c, 0x89, 0xeb, + 0x9f, 0x3a, 0x49, 0x7d, 0x4d, 0xce, 0x08, 0x76, 0x4f, 0xd1, 0x27, 0x00, 0xde, 0x4c, 0xb2, 0x31, + 0xbb, 0xb8, 0xa0, 0xd2, 0x49, 0x69, 0x6d, 0x4c, 0x82, 0x9e, 0x40, 0x49, 0x7a, 0x7c, 0x42, 0xa4, + 0x2b, 0x24, 0xa7, 0xc1, 0xc4, 0x49, 0xd7, 0xad, 0x66, 0x1e, 0x17, 0x8d, 0x70, 0xa8, 0x65, 0xa8, + 0x0d, 0x59, 0x16, 0x4a, 0x1d, 0x5f, 0xa6, 0x6e, 0x35, 0x0b, 0x9d, 0x07, 0x2d, 0x83, 0x4a, 0xef, + 0x17, 0x32, 0x9e, 0x49, 0x32, 0x30, 0x4a, 0xbc, 0xb4, 0x42, 0x3b, 0x60, 0xc7, 0x72, 0x77, 0x2f, + 0x98, 0x4f, 0x9c, 0x6c, 0xdd, 0x6a, 0x96, 0x3b, 0xff, 0x5f, 0x66, 0x16, 0x83, 0x61, 0x9f, 0xf9, + 0x04, 0x57, 0xe4, 0x55, 0x01, 0x6a, 0x43, 0xee, 0xd2, 0xe3, 0x01, 0x0d, 0x26, 0xc2, 0xc9, 0x69, + 0x54, 0xee, 0x47, 0xb7, 0xfe, 0xa8, 0xbe, 0x27, 0x46, 0x87, 0x57, 0x46, 0xe8, 0x7b, 0x28, 0x86, + 0x9c, 0xac, 0xa1, 0xcc, 0xdf, 0x00, 0xca, 0x42, 0xc8, 0xc9, 0x0a, 0xc8, 0x6d, 0x28, 0x85, 0x4c, + 0xc8, 0xb5, 0x07, 0xb8, 0x81, 0x87, 0xa2, 0x3a, 0xb2, 0x72, 0xf1, 0x14, 0xca, 0x53, 0x4f, 0x48, + 0x97, 0x06, 0x82, 0x70, 0xe9, 0x52, 0xdf, 0x29, 0xd4, 0xad, 0x66, 0x0a, 0x17, 0x95, 0xb4, 0xaf, + 0x85, 0x7d, 0x1f, 0x7d, 0x0c, 0x70, 0xc6, 0x66, 0x81, 0xef, 0x72, 0x76, 0x29, 0x9c, 0xa2, 0xb6, + 0xc8, 0x6b, 0x09, 0x66, 0x97, 0x02, 0xb9, 0xf0, 0x70, 0x26, 0x08, 0x77, 0x7d, 0x72, 0x46, 0x03, + 0xe2, 0xbb, 0x73, 0x8f, 0x53, 0xef, 0x74, 0x4a, 0x84, 0x53, 0xd2, 0x01, 0xbd, 0xd8, 0x0c, 0xe8, + 0x48, 0x10, 0xbe, 0x6b, 0x8c, 0x8f, 0x97, 0xb6, 0xbd, 0x40, 0xf2, 0x05, 0xae, 0xce, 0xae, 0x51, + 0xa1, 0x01, 0xd8, 0x62, 0x21, 0x24, 0xb9, 0x88, 0xb9, 0x2e, 0x6b, 0xd7, 0x4f, 0xff, 0x91, 0xab, + 0xb6, 0xdb, 0xf0, 0x5a, 0x11, 0x57, 0xa5, 0xaa, 0x04, 0x39, 0xbb, 0x74, 0xc7, 0x6c, 0x16, 0x48, + 0xa7, 0x52, 0xb7, 0x9a, 0x49, 0x9c, 0xe3, 0xec, 0xb2, 0xab, 0xf6, 0xb5, 0xd7, 0x50, 0x8c, 0x23, + 0x86, 0x9e, 0x41, 0xc6, 0x54, 0x97, 0xee, 0x89, 0x42, 0xa7, 0x14, 0xd1, 0x3a, 0xd2, 0x42, 0x1c, + 0x29, 0x55, 0x0b, 0xc5, 0x6b, 0x88, 0xfa, 0x4e, 0x42, 0x3b, 0x2e, 0xc5, 0xa4, 0x7d, 0xbf, 0xf6, + 0x1a, 0x1e, 0xfd, 0x6b, 0xfa, 0xc8, 0x86, 0xe4, 0x1b, 0xb2, 0xd0, 0xf7, 0xe4, 0xb1, 0x5a, 0xa2, + 0x17, 0x90, 0x9e, 0x7b, 0xd3, 0x19, 0xd1, 0xce, 0xd6, 0x25, 0xb5, 0x43, 0x83, 0xd5, 0x59, 0x6c, + 0x2c, 0xbe, 0x49, 0x7c, 0x6d, 0xd5, 0x76, 0xa0, 0x7a, 0x1d, 0x02, 0xd7, 0x38, 0xae, 0xc6, 0x1d, + 0xe7, 0x63, 0x3e, 0x1a, 0x7f, 0x24, 0xa0, 0x1c, 0x35, 0x0a, 0x26, 0x6f, 0x67, 0x44, 0x48, 0xf4, + 0x19, 0xe4, 0xc7, 0xde, 0x74, 0x4a, 0xb8, 0x4a, 0xcb, 0xa0, 0x50, 0x69, 0x99, 0x59, 0xd2, 0xd5, + 0xf2, 0xfe, 0x2e, 0xce, 0x19, 0x8b, 0xbe, 0x8f, 0x5e, 0x40, 0x36, 0x2a, 0xc9, 0x28, 0xea, 0xca, + 0x06, 0x4b, 0x78, 0xa9, 0x47, 0xcf, 0x21, 0xad, 0x13, 0xd2, 0x73, 0xa0, 0xd0, 0xf9, 0xdf, 0x32, + 0x3d, 0x55, 0x5b, 0xba, 0x6d, 0xb0, 0xd1, 0xa3, 0x2f, 0xa1, 0x20, 0x55, 0x3e, 0xd2, 0x95, 0x8b, + 0x90, 0xe8, 0xc1, 0x50, 0xee, 0x54, 0x5b, 0xab, 0xf9, 0x36, 0xd2, 0xca, 0xd1, 0x22, 0x24, 0x18, + 0xe4, 0x6a, 0xad, 0x48, 0x79, 0x43, 0x16, 0x22, 0xf4, 0xc6, 0xc4, 0xd5, 0x53, 0x48, 0x0f, 0x84, + 0x3c, 0x2e, 0x2d, 0xa5, 0x9a, 0xe9, 0xf8, 0xc0, 0xc8, 0xde, 0x64, 0x60, 0xfc, 0x90, 0xca, 0xa5, + 0xed, 0x4c, 0xe3, 0x57, 0x0b, 0x2a, 0x2b, 0xa4, 0x44, 0xc8, 0x02, 0xa1, 0x6e, 0x4c, 0x13, 0xce, + 0x19, 0xdf, 0x80, 0x09, 0x1f, 0x76, 0x7b, 0x4a, 0x8c, 0x8d, 0xf6, 0x7d, 0x30, 0xda, 0x82, 0x0c, + 0x27, 0x62, 0x36, 0x95, 0x11, 0x48, 0x28, 0x3e, 0x56, 0xb0, 0xd6, 0xe0, 0xc8, 0xa2, 0xf1, 0x57, + 0x02, 0xee, 0x47, 0x11, 0xed, 0x78, 0x72, 0x7c, 0x7e, 0xe7, 0x04, 0x7e, 0x0a, 0x59, 0x15, 0x0d, + 0x25, 0xc2, 0x49, 0xea, 0x8e, 0xbc, 0x86, 0xc2, 0xa5, 0xc5, 0x07, 0x90, 0xe8, 0x89, 0x2b, 0x8f, + 0x53, 0xda, 0x3c, 0x4e, 0x9e, 0x88, 0x3f, 0x4e, 0x77, 0xc4, 0x75, 0xe3, 0x77, 0x0b, 0xaa, 0x57, + 0x31, 0xbd, 0x33, 0xaa, 0x3f, 0x87, 0xac, 0x21, 0x72, 0x89, 0xe6, 0xc3, 0x28, 0x36, 0x43, 0xf3, + 0x09, 0x95, 0xe7, 0xc6, 0xf5, 0xd2, 0x4c, 0x35, 0x6b, 0x75, 0x28, 0x39, 0xf1, 0x2e, 0x3e, 0xa8, + 0x65, 0x57, 0x7d, 0x98, 0x78, 0xbf, 0x3e, 0x4c, 0xde, 0xba, 0x0f, 0x53, 0xef, 0xe0, 0x26, 0x7d, + 0xa3, 0x87, 0x3b, 0x86, 0x6d, 0xe6, 0xbf, 0xb1, 0x6d, 0x74, 0xe1, 0xc1, 0x06, 0x50, 0x11, 0x8d, + 0xeb, 0xfe, 0xb2, 0xde, 0xd9, 0x5f, 0x3f, 0xc3, 0x23, 0x4c, 0x04, 0x9b, 0xce, 0x49, 0xac, 0xf2, + 0x6e, 0x07, 0x39, 0x82, 0x94, 0x2f, 0xa3, 0x57, 0x22, 0x8f, 0xf5, 0xba, 0xf1, 0x18, 0x6a, 0xd7, + 0xb9, 0x37, 0x81, 0x36, 0xfe, 0xb4, 0xa0, 0x7c, 0x6c, 0x72, 0xb8, 0xdd, 0x95, 0x1b, 0xe4, 0x25, + 0x6e, 0x48, 0xde, 0x73, 0x48, 0xcf, 0x27, 0x2a, 0xd4, 0xe5, 0x90, 0x8e, 0xfd, 0x74, 0x1e, 0xbf, + 0x92, 0xd4, 0xc7, 0x46, 0xaf, 0x90, 0x3c, 0xa3, 0x53, 0x49, 0xb8, 0x66, 0x57, 0x21, 0x19, 0xb3, + 0x7c, 0xa9, 0x35, 0x38, 0xb2, 0x68, 0x7c, 0x07, 0x95, 0x55, 0x2e, 0x6b, 0x22, 0xc8, 0x9c, 0x04, + 0x52, 0x38, 0x96, 0x2e, 0xfe, 0x2b, 0xc7, 0x8f, 0x7b, 0x4a, 0x85, 0x23, 0x8b, 0xad, 0x5d, 0xa8, + 0x6c, 0xfc, 0x91, 0xa1, 0x0a, 0x14, 0x8e, 0x0e, 0x86, 0x87, 0xbd, 0x6e, 0xff, 0x65, 0xbf, 0xb7, + 0x6b, 0xdf, 0x43, 0x00, 0x99, 0x61, 0xff, 0xe0, 0xd5, 0x5e, 0xcf, 0xb6, 0x50, 0x1e, 0xd2, 0xfb, + 0x47, 0x7b, 0xa3, 0xbe, 0x9d, 0x50, 0xcb, 0xd1, 0xc9, 0xe0, 0xb0, 0x6b, 0x27, 0xb7, 0xbe, 0x85, + 0x42, 0x57, 0xff, 0x57, 0x0e, 0xb8, 0x4f, 0xb8, 0x3a, 0x70, 0x30, 0xc0, 0xfb, 0xdb, 0x7b, 0xf6, + 0x3d, 0x94, 0x85, 0xe4, 0x21, 0x56, 0x27, 0x73, 0x90, 0x3a, 0x1c, 0x0c, 0x47, 0x76, 0x02, 0x95, + 0x01, 0xb6, 0x8f, 0x46, 0x83, 0xee, 0x60, 0x7f, 0xbf, 0x3f, 0xb2, 0x93, 0x3b, 0x5f, 0x41, 0x85, + 0xb2, 0xd6, 0x9c, 0x4a, 0x22, 0x84, 0xf9, 0xa7, 0xfe, 0xe9, 0x49, 0xb4, 0xa3, 0xac, 0x6d, 0x56, + 0xed, 0x09, 0x6b, 0xcf, 0x65, 0x5b, 0x6b, 0xdb, 0xa6, 0x34, 0x4f, 0x33, 0x7a, 0xf7, 0xc5, 0xdf, + 0x01, 0x00, 0x00, 0xff, 0xff, 0x8d, 0xfe, 0x6c, 0x91, 0xd3, 0x0b, 0x00, 0x00, } diff --git a/go/vt/sqlparser/expression_rewriting.go b/go/vt/sqlparser/expression_rewriting.go index 514cafb4636..fed9e5dd8a4 100644 --- a/go/vt/sqlparser/expression_rewriting.go +++ b/go/vt/sqlparser/expression_rewriting.go @@ -36,6 +36,7 @@ type BindVarNeeds struct { NeedLastInsertID bool NeedDatabase bool NeedFoundRows bool + NeedRowCount bool NeedUserDefinedVariables bool } @@ -64,6 +65,9 @@ func RewriteAST(in Statement) (*RewriteASTResult, error) { if _, ok := er.bindVars[FoundRowsName]; ok { r.NeedFoundRows = true } + if _, ok := er.bindVars[RowCountName]; ok { + r.NeedRowCount = true + } if _, ok := er.bindVars[UserDefinedVariableName]; ok { r.NeedUserDefinedVariables = true } @@ -116,6 +120,9 @@ const ( //FoundRowsName is a reserved bind var name for found_rows() FoundRowsName = "__vtfrows" + //RowCountName is a reserved bind var name for row_count() + RowCountName = "__vtrcount" + //UserDefinedVariableName is what we prepend bind var names for user defined variables UserDefinedVariableName = "__vtudv" ) @@ -145,32 +152,7 @@ func (er *expressionRewriter) goingDown(cursor *Cursor) bool { return false } case *FuncExpr: - switch { - // last_insert_id() -> :__lastInsertId - case node.Name.EqualString("last_insert_id"): - if len(node.Exprs) > 0 { //last_insert_id(x) - er.err = vterrors.New(vtrpc.Code_UNIMPLEMENTED, "Argument to LAST_INSERT_ID() not supported") - } else { - cursor.Replace(bindVarExpression(LastInsertIDName)) - er.needBindVarFor(LastInsertIDName) - } - case er.shouldRewriteDatabaseFunc && - (node.Name.EqualString("database") || - node.Name.EqualString("schema")): - if len(node.Exprs) > 0 { - er.err = vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, "Syntax error. %s() takes no arguments", node.Name.String()) - } else { - cursor.Replace(bindVarExpression(DBVarName)) - er.needBindVarFor(DBVarName) - } - case node.Name.EqualString("found_rows"): - if len(node.Exprs) > 0 { - er.err = vterrors.New(vtrpc.Code_INVALID_ARGUMENT, "Arguments to FOUND_ROWS() not supported") - } else { - cursor.Replace(bindVarExpression(FoundRowsName)) - er.needBindVarFor(FoundRowsName) - } - } + er.funcRewrite(cursor, node) case *ColName: if node.Name.at == SingleAt { cursor.Replace(bindVarExpression(UserDefinedVariableName + node.Name.CompliantName())) @@ -180,6 +162,45 @@ func (er *expressionRewriter) goingDown(cursor *Cursor) bool { return true } +func (er *expressionRewriter) funcRewrite(cursor *Cursor, node *FuncExpr) { + switch { + // last_insert_id() -> :__lastInsertId + case node.Name.EqualString("last_insert_id"): + if len(node.Exprs) > 0 { //last_insert_id(x) + er.err = vterrors.New(vtrpc.Code_UNIMPLEMENTED, "Argument to LAST_INSERT_ID() not supported") + } else { + cursor.Replace(bindVarExpression(LastInsertIDName)) + er.needBindVarFor(LastInsertIDName) + } + // database() -> :__vtdbname + case er.shouldRewriteDatabaseFunc && + (node.Name.EqualString("database") || + node.Name.EqualString("schema")): + if len(node.Exprs) > 0 { + er.err = vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, "Syntax error. %s() takes no arguments", node.Name.String()) + } else { + cursor.Replace(bindVarExpression(DBVarName)) + er.needBindVarFor(DBVarName) + } + // found_rows() -> :__vtfrows + case node.Name.EqualString("found_rows"): + if len(node.Exprs) > 0 { + er.err = vterrors.New(vtrpc.Code_INVALID_ARGUMENT, "Arguments to FOUND_ROWS() not supported") + } else { + cursor.Replace(bindVarExpression(FoundRowsName)) + er.needBindVarFor(FoundRowsName) + } + // row_count() -> :__vtrcount + case node.Name.EqualString("row_count"): + if len(node.Exprs) > 0 { + er.err = vterrors.New(vtrpc.Code_INVALID_ARGUMENT, "Arguments to ROW_COUNT() not supported") + } else { + cursor.Replace(bindVarExpression(RowCountName)) + er.needBindVarFor(RowCountName) + } + } +} + // instead of creating new objects, we'll reuse this one var token = struct{}{} diff --git a/go/vt/sqlparser/expression_rewriting_test.go b/go/vt/sqlparser/expression_rewriting_test.go index 4989675f926..65433767afd 100644 --- a/go/vt/sqlparser/expression_rewriting_test.go +++ b/go/vt/sqlparser/expression_rewriting_test.go @@ -23,8 +23,8 @@ import ( ) type myTestCase struct { - in, expected string - liid, db, foundRows, udv bool + in, expected string + liid, db, foundRows, udv, rowCount bool } func TestRewrites(in *testing.T) { @@ -109,6 +109,11 @@ func TestRewrites(in *testing.T) { expected: "insert into t(id) values(:__vtudvxyx)", db: false, udv: true, }, + { + in: "select row_count()", + expected: "select :__vtrcount as `row_count()`", + rowCount: true, + }, } for _, tc := range tests { @@ -127,6 +132,7 @@ func TestRewrites(in *testing.T) { require.Equal(t, tc.liid, result.NeedLastInsertID, "should need last insert id") require.Equal(t, tc.db, result.NeedDatabase, "should need database name") require.Equal(t, tc.foundRows, result.NeedFoundRows, "should need found rows") + require.Equal(t, tc.rowCount, result.NeedRowCount, "should need row count") }) } } diff --git a/go/vt/vtgate/endtoend/main_test.go b/go/vt/vtgate/endtoend/main_test.go index e6fe2fa8b92..db8652f1e44 100644 --- a/go/vt/vtgate/endtoend/main_test.go +++ b/go/vt/vtgate/endtoend/main_test.go @@ -83,6 +83,12 @@ create table t1_last_insert_id( id1 bigint, primary key(id) ) Engine=InnoDB; + +create table t1_row_count( + id bigint not null, + id1 bigint, + primary key(id) +) Engine=InnoDB; ` vschema = &vschemapb.Keyspace{ @@ -168,6 +174,12 @@ create table t1_last_insert_id( Type: sqltypes.Int64, }}, }, + "t1_row_count": { + ColumnVindexes: []*vschemapb.ColumnVindex{{ + Column: "id", + Name: "hash", + }}, + }, }, } ) diff --git a/go/vt/vtgate/endtoend/row_count_test.go b/go/vt/vtgate/endtoend/row_count_test.go new file mode 100644 index 00000000000..e0d3c384dab --- /dev/null +++ b/go/vt/vtgate/endtoend/row_count_test.go @@ -0,0 +1,64 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package endtoend + +import ( + "context" + "fmt" + "testing" + + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/mysql" +) + +func TestRowCount(t *testing.T) { + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + defer conn.Close() + type tc struct { + query string + expected int + } + tests := []tc{{ + query: "insert into t1_row_count(id, id1) values(1, 1), (2, 1), (3, 3), (4, 3)", + expected: 4, + }, { + query: "select * from t1_row_count", + expected: -1, + }, { + query: "update t1_row_count set id1 = 500 where id in (1,3)", + expected: 2, + }, { + query: "show tables", + expected: -1, + }, { + query: "set @x = 24", + expected: 0, + }, { + query: "delete from t1_row_count", + expected: 4, + }} + + for _, test := range tests { + t.Run(test.query, func(t *testing.T) { + exec(t, conn, test.query) + qr := exec(t, conn, "select row_count()") + require.Equal(t, fmt.Sprintf("INT64(%d)", test.expected), qr.Rows[0][0].String()) + }) + } +} diff --git a/go/vt/vtgate/executor.go b/go/vt/vtgate/executor.go index da8396f336f..69eb0b7753a 100644 --- a/go/vt/vtgate/executor.go +++ b/go/vt/vtgate/executor.go @@ -108,7 +108,7 @@ type Executor struct { // and use the legacy one in production until we are comfortable with the new code. // it's temporary and should be removed once we can do everything using the new planning strategy type executeMethod interface { - execute(ctx context.Context, safeSession *SafeSession, sql string, bindVars map[string]*querypb.BindVariable, logStats *LogStats) (*sqltypes.Result, error) + execute(ctx context.Context, safeSession *SafeSession, sql string, bindVars map[string]*querypb.BindVariable, logStats *LogStats) (sqlparser.StatementType, *sqltypes.Result, error) } var executorOnce sync.Once @@ -161,11 +161,9 @@ func (e *Executor) Execute(ctx context.Context, method string, safeSession *Safe defer span.Finish() logStats := NewLogStats(ctx, method, sql, bindVars) - result, err = e.exec.execute(ctx, safeSession, sql, bindVars, logStats) - if err == nil { - safeSession.FoundRows = result.RowsAffected - } + stmtType, result, err := e.exec.execute(ctx, safeSession, sql, bindVars, logStats) logStats.Error = err + saveSessionStats(safeSession, stmtType, result, err) if result != nil && len(result.Rows) > *warnMemoryRows { warnings.Add("ResultsExceeded", 1) } @@ -179,21 +177,38 @@ func (e *Executor) Execute(ctx context.Context, method string, safeSession *Safe return result, err } -func (e *Executor) execute(ctx context.Context, safeSession *SafeSession, sql string, bindVars map[string]*querypb.BindVariable, logStats *LogStats) (*sqltypes.Result, error) { +func saveSessionStats(safeSession *SafeSession, stmtType sqlparser.StatementType, result *sqltypes.Result, err error) { + safeSession.RowCount = -1 + if err != nil { + return + } + safeSession.FoundRows = result.RowsAffected + if result.InsertID > 0 { + safeSession.LastInsertId = result.InsertID + } + switch stmtType { + case sqlparser.StmtInsert, sqlparser.StmtReplace, sqlparser.StmtUpdate, sqlparser.StmtDelete: + safeSession.RowCount = int64(result.RowsAffected) + case sqlparser.StmtDDL, sqlparser.StmtSet, sqlparser.StmtBegin, sqlparser.StmtCommit, sqlparser.StmtRollback: + safeSession.RowCount = 0 + } +} + +func (e *Executor) execute(ctx context.Context, safeSession *SafeSession, sql string, bindVars map[string]*querypb.BindVariable, logStats *LogStats) (sqlparser.StatementType, *sqltypes.Result, error) { //Start an implicit transaction if necessary. if !safeSession.Autocommit && !safeSession.InTransaction() { if err := e.txConn.Begin(ctx, safeSession); err != nil { - return nil, err + return 0, nil, err } } destKeyspace, destTabletType, dest, err := e.ParseDestinationTarget(safeSession.TargetString) if err != nil { - return nil, err + return 0, nil, err } if safeSession.InTransaction() && destTabletType != topodatapb.TabletType_MASTER { - return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "transactions are supported only for master tablet types, current type: %v", destTabletType) + return 0, nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "transactions are supported only for master tablet types, current type: %v", destTabletType) } if bindVars == nil { bindVars = make(map[string]*querypb.BindVariable) @@ -216,15 +231,19 @@ func (e *Executor) execute(ctx context.Context, safeSession *SafeSession, sql st switch stmtType { case sqlparser.StmtSelect, sqlparser.StmtInsert, sqlparser.StmtReplace, sqlparser.StmtUpdate, sqlparser.StmtDelete, sqlparser.StmtDDL, sqlparser.StmtUse, sqlparser.StmtExplain, sqlparser.StmtOther: - return nil, vterrors.New(vtrpcpb.Code_INTERNAL, "BUG: not reachable as handled with plan execute") + return 0, nil, vterrors.New(vtrpcpb.Code_INTERNAL, "BUG: not reachable as handled with plan execute") case sqlparser.StmtSet: - return e.handleSet(ctx, safeSession, sql, logStats) + qr, err := e.handleSet(ctx, safeSession, sql, logStats) + return sqlparser.StmtSet, qr, err case sqlparser.StmtShow: - return e.handleShow(ctx, safeSession, sql, bindVars, dest, destKeyspace, destTabletType, logStats) + qr, err := e.handleShow(ctx, safeSession, sql, bindVars, dest, destKeyspace, destTabletType, logStats) + return sqlparser.StmtShow, qr, err case sqlparser.StmtComment: - return e.handleComment(sql) + // Effectively should be done through new plan. + // There are some statements which are not planned for special comments. + return sqlparser.StmtComment, &sqltypes.Result{}, nil } - return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "unrecognized statement: %s", sql) + return 0, nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "unrecognized statement: %s", sql) } // addNeededBindVars adds bind vars that are needed by the plan @@ -248,6 +267,10 @@ func (e *Executor) addNeededBindVars(bindVarNeeds sqlparser.BindVarNeeds, bindVa bindVars[sqlparser.FoundRowsName] = sqltypes.Uint64BindVariable(session.FoundRows) } + if bindVarNeeds.NeedRowCount { + bindVars[sqlparser.RowCountName] = sqltypes.Int64BindVariable(session.RowCount) + } + return nil } @@ -1033,12 +1056,6 @@ func (e *Executor) handleOther(ctx context.Context, safeSession *SafeSession, sq return result, err } -func (e *Executor) handleComment(sql string) (*sqltypes.Result, error) { - _, _ = sqlparser.ExtractMysqlComment(sql) - // Not sure if this is a good idea. - return &sqltypes.Result{}, nil -} - // StreamExecute executes a streaming query. func (e *Executor) StreamExecute(ctx context.Context, method string, safeSession *SafeSession, sql string, bindVars map[string]*querypb.BindVariable, target querypb.Target, callback func(*sqltypes.Result) error) (err error) { logStats := NewLogStats(ctx, method, sql, bindVars) diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index 29e8f9859c0..163d661e78d 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -288,6 +288,35 @@ func TestFoundRows(t *testing.T) { utils.MustMatch(t, result, wantResult, "Mismatch") } +func TestRowCount(t *testing.T) { + executor, _, _, _ := createExecutorEnv() + executor.normalize = true + logChan := QueryLogger.Subscribe("Test") + defer QueryLogger.Unsubscribe(logChan) + + _, err := executorExec(executor, "select 42", map[string]*querypb.BindVariable{}) + require.NoError(t, err) + testRowCount(t, executor, -1) + + _, err = executorExec(executor, "update user set name = 'abc' where id in (42, 24)", map[string]*querypb.BindVariable{}) + require.NoError(t, err) + testRowCount(t, executor, 2) +} + +func testRowCount(t *testing.T, executor *Executor, wantRowCount int64) { + result, err := executorExec(executor, "select row_count()", map[string]*querypb.BindVariable{}) + wantResult := &sqltypes.Result{ + Fields: []*querypb.Field{ + {Name: "row_count()", Type: sqltypes.Int64}, + }, + Rows: [][]sqltypes.Value{{ + sqltypes.NewInt64(wantRowCount), + }}, + } + require.NoError(t, err) + utils.MustMatch(t, result, wantResult, "Mismatch") +} + func TestSelectLastInsertIdInUnion(t *testing.T) { executor, sbc1, _, _ := createExecutorEnv() executor.normalize = true diff --git a/go/vt/vtgate/executor_test.go b/go/vt/vtgate/executor_test.go index 120009d0d65..278bd3f3c3d 100644 --- a/go/vt/vtgate/executor_test.go +++ b/go/vt/vtgate/executor_test.go @@ -29,6 +29,8 @@ import ( "testing" "time" + "vitess.io/vitess/go/test/utils" + "vitess.io/vitess/go/vt/topo" "github.com/golang/protobuf/proto" @@ -325,12 +327,10 @@ func TestExecutorAutocommit(t *testing.T) { if err != nil { t.Fatal(err) } - wantSession := &vtgatepb.Session{TargetString: "@master", InTransaction: true, FoundRows: 1} + wantSession := &vtgatepb.Session{TargetString: "@master", InTransaction: true, FoundRows: 1, RowCount: -1} testSession := *session.Session testSession.ShardSessions = nil - if !proto.Equal(&testSession, wantSession) { - t.Errorf("autocommit=0: %v, want %v", testSession, wantSession) - } + utils.MustMatch(t, wantSession, &testSession, "session does not match for autocommit=0") logStats := testQueryLog(t, logChan, "TestExecute", "SELECT", "select id from main1", 1) if logStats.CommitTime != 0 { @@ -359,10 +359,8 @@ func TestExecutorAutocommit(t *testing.T) { if err != nil { t.Fatal(err) } - wantSession = &vtgatepb.Session{Autocommit: true, TargetString: "@master", FoundRows: 1} - if !proto.Equal(session.Session, wantSession) { - t.Errorf("autocommit=1: %v, want %v", session.Session, wantSession) - } + wantSession = &vtgatepb.Session{Autocommit: true, TargetString: "@master", FoundRows: 1, RowCount: 1} + utils.MustMatch(t, wantSession, session.Session, "session does not match for autocommit=1") if got, want := sbclookup.AsTransactionCount.Get(), startCount+1; got != want { t.Errorf("Commit count: %d, want %d", got, want) } @@ -388,12 +386,10 @@ func TestExecutorAutocommit(t *testing.T) { if err != nil { t.Fatal(err) } - wantSession = &vtgatepb.Session{InTransaction: true, Autocommit: true, TargetString: "@master", FoundRows: 1} + wantSession = &vtgatepb.Session{InTransaction: true, Autocommit: true, TargetString: "@master", FoundRows: 1, RowCount: 1} testSession = *session.Session testSession.ShardSessions = nil - if !proto.Equal(&testSession, wantSession) { - t.Errorf("autocommit=1: %v, want %v", &testSession, wantSession) - } + utils.MustMatch(t, wantSession, &testSession, "session does not match for autocommit=1") if got, want := sbclookup.CommitCount.Get(), startCount; got != want { t.Errorf("Commit count: %d, want %d", got, want) } @@ -1025,10 +1021,8 @@ func TestExecutorUse(t *testing.T) { if err != nil { t.Error(err) } - wantSession := &vtgatepb.Session{Autocommit: true, TargetString: want[i]} - if !proto.Equal(session.Session, wantSession) { - t.Errorf("%s: %v, want %v", stmt, session.Session, wantSession) - } + wantSession := &vtgatepb.Session{Autocommit: true, TargetString: want[i], RowCount: -1} + utils.MustMatch(t, wantSession, session.Session, "session does not match") } _, err := executor.Execute(context.Background(), "TestExecute", NewSafeSession(&vtgatepb.Session{}), "use 1", nil) diff --git a/go/vt/vtgate/fallback_executor.go b/go/vt/vtgate/fallback_executor.go index b5fa6732bdd..f1f68604c8b 100644 --- a/go/vt/vtgate/fallback_executor.go +++ b/go/vt/vtgate/fallback_executor.go @@ -19,6 +19,8 @@ package vtgate import ( "context" + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/proto/query" "vitess.io/vitess/go/vt/vtgate/planbuilder" @@ -36,10 +38,10 @@ This method implements the fall back logic. If exA(plan execute) is not able to plan the statement then it fall backs to exB(execute) method. There is no fallback for parsing errors. */ -func (f *fallbackExecutor) execute(ctx context.Context, safeSession *SafeSession, sql string, bindVars map[string]*query.BindVariable, logStats *LogStats) (*sqltypes.Result, error) { - qr, err := f.exA.execute(ctx, safeSession, sql, bindVars, logStats) +func (f *fallbackExecutor) execute(ctx context.Context, safeSession *SafeSession, sql string, bindVars map[string]*query.BindVariable, logStats *LogStats) (sqlparser.StatementType, *sqltypes.Result, error) { + stmtType, qr, err := f.exA.execute(ctx, safeSession, sql, bindVars, logStats) if err == planbuilder.ErrPlanNotSupported { return f.exB.execute(ctx, safeSession, sql, bindVars, logStats) } - return qr, err + return stmtType, qr, err } diff --git a/go/vt/vtgate/plan_execute.go b/go/vt/vtgate/plan_execute.go index dddff3542a1..db5903bbf0d 100644 --- a/go/vt/vtgate/plan_execute.go +++ b/go/vt/vtgate/plan_execute.go @@ -81,13 +81,13 @@ func NewTestExecutor(ctx context.Context, strat func(executor *Executor) execute return e } -func (e *planExecute) execute(ctx context.Context, safeSession *SafeSession, sql string, bindVars map[string]*querypb.BindVariable, logStats *LogStats) (*sqltypes.Result, error) { +func (e *planExecute) execute(ctx context.Context, safeSession *SafeSession, sql string, bindVars map[string]*querypb.BindVariable, logStats *LogStats) (sqlparser.StatementType, *sqltypes.Result, error) { // 1: Prepare before planning and execution // Start an implicit transaction if necessary. err := e.startTxIfNecessary(ctx, safeSession) if err != nil { - return nil, err + return 0, nil, err } if bindVars == nil { @@ -97,7 +97,7 @@ func (e *planExecute) execute(ctx context.Context, safeSession *SafeSession, sql query, comments := sqlparser.SplitMarginComments(sql) vcursor, err := newVCursorImpl(ctx, safeSession, comments, e.e, logStats, e.e.vm, e.e.resolver.resolver) if err != nil { - return nil, err + return 0, nil, err } // 2: Create a plan for the query @@ -110,13 +110,13 @@ func (e *planExecute) execute(ctx context.Context, safeSession *SafeSession, sql logStats, ) if err == planbuilder.ErrPlanNotSupported { - return nil, err + return 0, nil, err } execStart := e.logPlanningFinished(logStats, sql) if err != nil { safeSession.ClearWarnings() - return nil, err + return 0, nil, err } if plan.Type != sqlparser.StmtShow { @@ -127,18 +127,21 @@ func (e *planExecute) execute(ctx context.Context, safeSession *SafeSession, sql // will fall through and be handled through planning switch plan.Type { case sqlparser.StmtBegin: - return e.e.handleBegin(ctx, safeSession, vcursor.tabletType, logStats) + qr, err := e.e.handleBegin(ctx, safeSession, vcursor.tabletType, logStats) + return sqlparser.StmtBegin, qr, err case sqlparser.StmtCommit: - return e.e.handleCommit(ctx, safeSession, logStats) + qr, err := e.e.handleCommit(ctx, safeSession, logStats) + return sqlparser.StmtCommit, qr, err case sqlparser.StmtRollback: - return e.e.handleRollback(ctx, safeSession, logStats) + qr, err := e.e.handleRollback(ctx, safeSession, logStats) + return sqlparser.StmtRollback, qr, err } // 3: Prepare for execution err = e.e.addNeededBindVars(plan.BindVarNeeds, bindVars, safeSession) if err != nil { logStats.Error = err - return nil, err + return 0, nil, err } if plan.Instructions.NeedsTransaction() { @@ -158,12 +161,12 @@ func (e *planExecute) startTxIfNecessary(ctx context.Context, safeSession *SafeS return nil } -func (e *planExecute) insideTransaction(ctx context.Context, safeSession *SafeSession, logStats *LogStats, f currFunc) (*sqltypes.Result, error) { +func (e *planExecute) insideTransaction(ctx context.Context, safeSession *SafeSession, logStats *LogStats, f currFunc) (sqlparser.StatementType, *sqltypes.Result, error) { mustCommit := false if safeSession.Autocommit && !safeSession.InTransaction() { mustCommit = true if err := e.e.txConn.Begin(ctx, safeSession); err != nil { - return nil, err + return 0, nil, err } } @@ -178,9 +181,9 @@ func (e *planExecute) insideTransaction(ctx context.Context, safeSession *SafeSe safeSession.SetAutocommittable(mustCommit) // Execute! - result, err := f(logStats, safeSession) + stmtType, result, err := f(logStats, safeSession) if err != nil { - return nil, err + return 0, nil, err } if mustCommit { @@ -190,22 +193,19 @@ func (e *planExecute) insideTransaction(ctx context.Context, safeSession *SafeSe commitStart := time.Now() if err := e.e.txConn.Commit(ctx, safeSession); err != nil { - return nil, err + return 0, nil, err } logStats.CommitTime = time.Since(commitStart) } - return result, nil + return stmtType, result, nil } -type currFunc func(*LogStats, *SafeSession) (*sqltypes.Result, error) +type currFunc func(*LogStats, *SafeSession) (sqlparser.StatementType, *sqltypes.Result, error) func (e *planExecute) executePlan(ctx context.Context, plan *engine.Plan, vcursor *vcursorImpl, bindVars map[string]*querypb.BindVariable, execStart time.Time) currFunc { - return func(logStats *LogStats, safeSession *SafeSession) (*sqltypes.Result, error) { + return func(logStats *LogStats, safeSession *SafeSession) (sqlparser.StatementType, *sqltypes.Result, error) { // 4: Execute! qr, err := plan.Instructions.Execute(vcursor, bindVars, true) - if err == nil && qr != nil && qr.InsertID > 0 { - safeSession.LastInsertId = qr.InsertID - } // 5: Log and add statistics errCount := e.logExecutionEnd(logStats, execStart, plan, err, qr) @@ -216,7 +216,7 @@ func (e *planExecute) executePlan(ctx context.Context, plan *engine.Plan, vcurso _ = e.e.txConn.Rollback(ctx, safeSession) err = vterrors.Errorf(vtrpcpb.Code_ABORTED, "transaction rolled back due to partial DML execution: %v", err) } - return qr, err + return plan.Type, qr, err } } diff --git a/go/vt/vtgate/plan_executor_test.go b/go/vt/vtgate/plan_executor_test.go index 792c762cfdc..33281bb364f 100644 --- a/go/vt/vtgate/plan_executor_test.go +++ b/go/vt/vtgate/plan_executor_test.go @@ -983,10 +983,8 @@ func TestPlanExecutorUse(t *testing.T) { if err != nil { t.Error(err) } - wantSession := &vtgatepb.Session{Autocommit: true, TargetString: want[i]} - if !proto.Equal(session.Session, wantSession) { - t.Errorf("%s: %v, want %v", stmt, session.Session, wantSession) - } + wantSession := &vtgatepb.Session{Autocommit: true, TargetString: want[i], RowCount: -1} + utils.MustMatch(t, wantSession, session.Session, "session does not match") } _, err := executor.Execute(context.Background(), "TestExecute", NewSafeSession(&vtgatepb.Session{}), "use 1", nil) diff --git a/proto/vtgate.proto b/proto/vtgate.proto index c68bf742163..761e478957d 100644 --- a/proto/vtgate.proto +++ b/proto/vtgate.proto @@ -117,6 +117,9 @@ message Session { // system_variables keeps track of all session variables set for this connection map system_variables = 14; + + // row_count keeps track of the last seen rows affected for this session + int64 row_count = 15; } // ExecuteRequest is the payload to Execute.