2017-05-06 02:21:12 +03:00
|
|
|
/*
|
2019-10-21 17:30:02 +03:00
|
|
|
Copyright 2019 The Vitess Authors.
|
2017-05-06 02:21:12 +03:00
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
2015-11-10 10:11:15 +03:00
|
|
|
|
|
|
|
package sqltypes
|
|
|
|
|
2017-04-18 18:17:34 +03:00
|
|
|
import (
|
2021-05-07 18:48:40 +03:00
|
|
|
"google.golang.org/protobuf/proto"
|
2017-04-18 18:17:34 +03:00
|
|
|
|
2018-02-27 22:58:59 +03:00
|
|
|
"vitess.io/vitess/go/vt/vterrors"
|
2017-04-18 18:17:34 +03:00
|
|
|
|
2018-02-27 22:58:59 +03:00
|
|
|
querypb "vitess.io/vitess/go/vt/proto/query"
|
2017-04-18 18:17:34 +03:00
|
|
|
)
|
2015-11-10 10:11:15 +03:00
|
|
|
|
|
|
|
// This file contains the proto3 conversion functions for the structures
|
|
|
|
// defined here.
|
|
|
|
|
2017-03-17 22:23:54 +03:00
|
|
|
// RowToProto3 converts []Value to proto3.
|
|
|
|
func RowToProto3(row []Value) *querypb.Row {
|
|
|
|
result := &querypb.Row{}
|
2021-04-23 17:41:01 +03:00
|
|
|
_ = RowToProto3Inplace(row, result)
|
2021-04-23 17:32:55 +03:00
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// RowToProto3Inplace converts []Value to proto3 and stores the conversion in the provided Row
|
2021-04-23 17:41:01 +03:00
|
|
|
func RowToProto3Inplace(row []Value, result *querypb.Row) int {
|
2021-04-23 17:32:55 +03:00
|
|
|
if result.Lengths == nil {
|
|
|
|
result.Lengths = make([]int64, 0, len(row))
|
|
|
|
} else {
|
|
|
|
result.Lengths = result.Lengths[:0]
|
|
|
|
}
|
2017-03-17 22:23:54 +03:00
|
|
|
total := 0
|
|
|
|
for _, c := range row {
|
|
|
|
if c.IsNull() {
|
|
|
|
result.Lengths = append(result.Lengths, -1)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
length := c.Len()
|
|
|
|
result.Lengths = append(result.Lengths, int64(length))
|
|
|
|
total += length
|
|
|
|
}
|
2021-04-23 17:32:55 +03:00
|
|
|
if result.Values == nil {
|
|
|
|
result.Values = make([]byte, 0, total)
|
|
|
|
} else {
|
|
|
|
result.Values = result.Values[:0]
|
|
|
|
}
|
2017-03-17 22:23:54 +03:00
|
|
|
for _, c := range row {
|
|
|
|
if c.IsNull() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
result.Values = append(result.Values, c.Raw()...)
|
|
|
|
}
|
2021-04-23 17:32:55 +03:00
|
|
|
return total
|
2017-03-17 22:23:54 +03:00
|
|
|
}
|
|
|
|
|
2015-11-10 10:11:15 +03:00
|
|
|
// RowsToProto3 converts [][]Value to proto3.
|
2015-11-12 11:13:54 +03:00
|
|
|
func RowsToProto3(rows [][]Value) []*querypb.Row {
|
2015-11-10 10:11:15 +03:00
|
|
|
if len(rows) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-11-12 11:13:54 +03:00
|
|
|
result := make([]*querypb.Row, len(rows))
|
2015-11-10 10:11:15 +03:00
|
|
|
for i, r := range rows {
|
2017-03-17 22:23:54 +03:00
|
|
|
result[i] = RowToProto3(r)
|
2015-11-10 10:11:15 +03:00
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2015-11-17 23:59:45 +03:00
|
|
|
// proto3ToRows converts a proto3 rows to [][]Value. The function is private
|
|
|
|
// because it uses the trusted API.
|
|
|
|
func proto3ToRows(fields []*querypb.Field, rows []*querypb.Row) [][]Value {
|
2015-11-10 10:11:15 +03:00
|
|
|
if len(rows) == 0 {
|
2015-11-19 01:53:43 +03:00
|
|
|
// TODO(sougou): This is needed for backward compatibility.
|
|
|
|
// Remove when it's not needed any more.
|
|
|
|
return [][]Value{}
|
2015-11-10 10:11:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
result := make([][]Value, len(rows))
|
|
|
|
for i, r := range rows {
|
2015-11-17 23:59:45 +03:00
|
|
|
result[i] = MakeRowTrusted(fields, r)
|
2015-11-10 10:11:15 +03:00
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// ResultToProto3 converts Result to proto3.
|
2015-11-12 11:13:54 +03:00
|
|
|
func ResultToProto3(qr *Result) *querypb.QueryResult {
|
2015-11-10 10:11:15 +03:00
|
|
|
if qr == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2015-11-12 11:13:54 +03:00
|
|
|
return &querypb.QueryResult{
|
2015-11-10 10:11:15 +03:00
|
|
|
Fields: qr.Fields,
|
|
|
|
RowsAffected: qr.RowsAffected,
|
|
|
|
InsertId: qr.InsertID,
|
|
|
|
Rows: RowsToProto3(qr.Rows),
|
2022-02-08 20:08:24 +03:00
|
|
|
Info: qr.Info,
|
2015-11-10 10:11:15 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-17 23:59:45 +03:00
|
|
|
// Proto3ToResult converts a proto3 Result to an internal data structure. This function
|
2015-11-18 02:15:10 +03:00
|
|
|
// should be used only if the field info is populated in qr.
|
|
|
|
func Proto3ToResult(qr *querypb.QueryResult) *Result {
|
|
|
|
if qr == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return &Result{
|
|
|
|
Fields: qr.Fields,
|
|
|
|
RowsAffected: qr.RowsAffected,
|
|
|
|
InsertID: qr.InsertId,
|
|
|
|
Rows: proto3ToRows(qr.Fields, qr.Rows),
|
2022-02-08 20:08:24 +03:00
|
|
|
Info: qr.Info,
|
2015-11-18 02:15:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// CustomProto3ToResult converts a proto3 Result to an internal data structure. This function
|
2015-11-17 23:59:45 +03:00
|
|
|
// takes a separate fields input because not all QueryResults contain the field info.
|
|
|
|
// In particular, only the first packet of streaming queries contain the field info.
|
2015-11-18 02:15:10 +03:00
|
|
|
func CustomProto3ToResult(fields []*querypb.Field, qr *querypb.QueryResult) *Result {
|
2015-11-10 10:11:15 +03:00
|
|
|
if qr == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return &Result{
|
|
|
|
Fields: qr.Fields,
|
|
|
|
RowsAffected: qr.RowsAffected,
|
|
|
|
InsertID: qr.InsertId,
|
2015-11-17 23:59:45 +03:00
|
|
|
Rows: proto3ToRows(fields, qr.Rows),
|
2015-11-10 10:11:15 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-17 23:59:45 +03:00
|
|
|
// ResultsToProto3 converts []Result to proto3.
|
|
|
|
func ResultsToProto3(qr []Result) []*querypb.QueryResult {
|
|
|
|
if len(qr) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
result := make([]*querypb.QueryResult, len(qr))
|
|
|
|
for i, q := range qr {
|
|
|
|
result[i] = ResultToProto3(&q)
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2015-11-10 10:11:15 +03:00
|
|
|
// Proto3ToResults converts proto3 results to []Result.
|
2015-11-12 11:13:54 +03:00
|
|
|
func Proto3ToResults(qr []*querypb.QueryResult) []Result {
|
2015-11-10 10:11:15 +03:00
|
|
|
if len(qr) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
result := make([]Result, len(qr))
|
|
|
|
for i, q := range qr {
|
2015-11-18 02:15:10 +03:00
|
|
|
result[i] = *Proto3ToResult(q)
|
2015-11-10 10:11:15 +03:00
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
2016-12-20 10:29:19 +03:00
|
|
|
|
|
|
|
// QueryResponsesToProto3 converts []QueryResponse to proto3.
|
|
|
|
func QueryResponsesToProto3(qr []QueryResponse) []*querypb.ResultWithError {
|
|
|
|
if len(qr) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
result := make([]*querypb.ResultWithError, len(qr))
|
|
|
|
for i, q := range qr {
|
2016-12-29 11:35:41 +03:00
|
|
|
result[i] = &querypb.ResultWithError{
|
|
|
|
Result: ResultToProto3(q.QueryResult),
|
2017-02-22 06:35:44 +03:00
|
|
|
Error: vterrors.ToVTRPC(q.QueryError),
|
2016-12-29 11:35:41 +03:00
|
|
|
}
|
2016-12-20 10:29:19 +03:00
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// Proto3ToQueryReponses converts proto3 queryResponse to []QueryResponse.
|
|
|
|
func Proto3ToQueryReponses(qr []*querypb.ResultWithError) []QueryResponse {
|
|
|
|
if len(qr) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
result := make([]QueryResponse, len(qr))
|
|
|
|
for i, q := range qr {
|
2016-12-29 11:35:41 +03:00
|
|
|
result[i] = QueryResponse{
|
|
|
|
QueryResult: Proto3ToResult(q.Result),
|
2017-02-22 06:35:44 +03:00
|
|
|
QueryError: vterrors.FromVTRPC(q.Error),
|
2016-12-29 11:35:41 +03:00
|
|
|
}
|
2016-12-20 10:29:19 +03:00
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
2017-04-18 18:17:34 +03:00
|
|
|
|
|
|
|
// Proto3ResultsEqual compares two arrays of proto3 Result.
|
|
|
|
// reflect.DeepEqual shouldn't be used because of the protos.
|
|
|
|
func Proto3ResultsEqual(r1, r2 []*querypb.QueryResult) bool {
|
|
|
|
if len(r1) != len(r2) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for i, r := range r1 {
|
|
|
|
if !proto.Equal(r, r2[i]) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Proto3QueryResponsesEqual compares two arrays of proto3 QueryResponse.
|
|
|
|
// reflect.DeepEqual shouldn't be used because of the protos.
|
|
|
|
func Proto3QueryResponsesEqual(r1, r2 []*querypb.ResultWithError) bool {
|
|
|
|
if len(r1) != len(r2) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for i, r := range r1 {
|
|
|
|
if !proto.Equal(r, r2[i]) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Proto3ValuesEqual compares two arrays of proto3 Value.
|
|
|
|
func Proto3ValuesEqual(v1, v2 []*querypb.Value) bool {
|
|
|
|
if len(v1) != len(v2) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for i, v := range v1 {
|
|
|
|
if !proto.Equal(v, v2[i]) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|