github.com/team-ide/go-dialect@v1.9.20/vitess/sqltypes/proto3.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package sqltypes
    18  
    19  import (
    20  	"google.golang.org/protobuf/proto"
    21  
    22  	"github.com/team-ide/go-dialect/vitess/vterrors"
    23  
    24  	querypb "github.com/team-ide/go-dialect/vitess/query"
    25  )
    26  
    27  // This file contains the proto3 conversion functions for the structures
    28  // defined here.
    29  
    30  // RowToProto3 converts []Value to proto3.
    31  func RowToProto3(row []Value) *querypb.Row {
    32  	result := &querypb.Row{}
    33  	_ = RowToProto3Inplace(row, result)
    34  	return result
    35  }
    36  
    37  // RowToProto3Inplace converts []Value to proto3 and stores the conversion in the provided Row
    38  func RowToProto3Inplace(row []Value, result *querypb.Row) int {
    39  	if result.Lengths == nil {
    40  		result.Lengths = make([]int64, 0, len(row))
    41  	} else {
    42  		result.Lengths = result.Lengths[:0]
    43  	}
    44  	total := 0
    45  	for _, c := range row {
    46  		if c.IsNull() {
    47  			result.Lengths = append(result.Lengths, -1)
    48  			continue
    49  		}
    50  		length := c.Len()
    51  		result.Lengths = append(result.Lengths, int64(length))
    52  		total += length
    53  	}
    54  	if result.Values == nil {
    55  		result.Values = make([]byte, 0, total)
    56  	} else {
    57  		result.Values = result.Values[:0]
    58  	}
    59  	for _, c := range row {
    60  		if c.IsNull() {
    61  			continue
    62  		}
    63  		result.Values = append(result.Values, c.Raw()...)
    64  	}
    65  	return total
    66  }
    67  
    68  // RowsToProto3 converts [][]Value to proto3.
    69  func RowsToProto3(rows [][]Value) []*querypb.Row {
    70  	if len(rows) == 0 {
    71  		return nil
    72  	}
    73  
    74  	result := make([]*querypb.Row, len(rows))
    75  	for i, r := range rows {
    76  		result[i] = RowToProto3(r)
    77  	}
    78  	return result
    79  }
    80  
    81  // proto3ToRows converts a proto3 rows to [][]Value. The function is private
    82  // because it uses the trusted API.
    83  func proto3ToRows(fields []*querypb.Field, rows []*querypb.Row) [][]Value {
    84  	if len(rows) == 0 {
    85  		// TODO(sougou): This is needed for backward compatibility.
    86  		// Remove when it's not needed any more.
    87  		return [][]Value{}
    88  	}
    89  
    90  	result := make([][]Value, len(rows))
    91  	for i, r := range rows {
    92  		result[i] = MakeRowTrusted(fields, r)
    93  	}
    94  	return result
    95  }
    96  
    97  // ResultToProto3 converts Result to proto3.
    98  func ResultToProto3(qr *Result) *querypb.QueryResult {
    99  	if qr == nil {
   100  		return nil
   101  	}
   102  	return &querypb.QueryResult{
   103  		Fields:       qr.Fields,
   104  		RowsAffected: qr.RowsAffected,
   105  		InsertId:     qr.InsertID,
   106  		Rows:         RowsToProto3(qr.Rows),
   107  	}
   108  }
   109  
   110  // Proto3ToResult converts a proto3 Result to an internal data structure. This function
   111  // should be used only if the field info is populated in qr.
   112  func Proto3ToResult(qr *querypb.QueryResult) *Result {
   113  	if qr == nil {
   114  		return nil
   115  	}
   116  	return &Result{
   117  		Fields:       qr.Fields,
   118  		RowsAffected: qr.RowsAffected,
   119  		InsertID:     qr.InsertId,
   120  		Rows:         proto3ToRows(qr.Fields, qr.Rows),
   121  	}
   122  }
   123  
   124  // CustomProto3ToResult converts a proto3 Result to an internal data structure. This function
   125  // takes a separate fields input because not all QueryResults contain the field info.
   126  // In particular, only the first packet of streaming queries contain the field info.
   127  func CustomProto3ToResult(fields []*querypb.Field, qr *querypb.QueryResult) *Result {
   128  	if qr == nil {
   129  		return nil
   130  	}
   131  	return &Result{
   132  		Fields:       qr.Fields,
   133  		RowsAffected: qr.RowsAffected,
   134  		InsertID:     qr.InsertId,
   135  		Rows:         proto3ToRows(fields, qr.Rows),
   136  	}
   137  }
   138  
   139  // ResultsToProto3 converts []Result to proto3.
   140  func ResultsToProto3(qr []Result) []*querypb.QueryResult {
   141  	if len(qr) == 0 {
   142  		return nil
   143  	}
   144  	result := make([]*querypb.QueryResult, len(qr))
   145  	for i, q := range qr {
   146  		result[i] = ResultToProto3(&q)
   147  	}
   148  	return result
   149  }
   150  
   151  // Proto3ToResults converts proto3 results to []Result.
   152  func Proto3ToResults(qr []*querypb.QueryResult) []Result {
   153  	if len(qr) == 0 {
   154  		return nil
   155  	}
   156  	result := make([]Result, len(qr))
   157  	for i, q := range qr {
   158  		result[i] = *Proto3ToResult(q)
   159  	}
   160  	return result
   161  }
   162  
   163  // QueryResponsesToProto3 converts []QueryResponse to proto3.
   164  func QueryResponsesToProto3(qr []QueryResponse) []*querypb.ResultWithError {
   165  	if len(qr) == 0 {
   166  		return nil
   167  	}
   168  	result := make([]*querypb.ResultWithError, len(qr))
   169  	for i, q := range qr {
   170  		result[i] = &querypb.ResultWithError{
   171  			Result: ResultToProto3(q.QueryResult),
   172  			Error:  vterrors.ToVTRPC(q.QueryError),
   173  		}
   174  	}
   175  	return result
   176  }
   177  
   178  // Proto3ToQueryReponses converts proto3 queryResponse to []QueryResponse.
   179  func Proto3ToQueryReponses(qr []*querypb.ResultWithError) []QueryResponse {
   180  	if len(qr) == 0 {
   181  		return nil
   182  	}
   183  	result := make([]QueryResponse, len(qr))
   184  	for i, q := range qr {
   185  		result[i] = QueryResponse{
   186  			QueryResult: Proto3ToResult(q.Result),
   187  			QueryError:  vterrors.FromVTRPC(q.Error),
   188  		}
   189  	}
   190  	return result
   191  }
   192  
   193  // Proto3ResultsEqual compares two arrays of proto3 Result.
   194  // reflect.DeepEqual shouldn't be used because of the protos.
   195  func Proto3ResultsEqual(r1, r2 []*querypb.QueryResult) bool {
   196  	if len(r1) != len(r2) {
   197  		return false
   198  	}
   199  	for i, r := range r1 {
   200  		if !proto.Equal(r, r2[i]) {
   201  			return false
   202  		}
   203  	}
   204  	return true
   205  }
   206  
   207  // Proto3QueryResponsesEqual compares two arrays of proto3 QueryResponse.
   208  // reflect.DeepEqual shouldn't be used because of the protos.
   209  func Proto3QueryResponsesEqual(r1, r2 []*querypb.ResultWithError) bool {
   210  	if len(r1) != len(r2) {
   211  		return false
   212  	}
   213  	for i, r := range r1 {
   214  		if !proto.Equal(r, r2[i]) {
   215  			return false
   216  		}
   217  	}
   218  	return true
   219  }
   220  
   221  // Proto3ValuesEqual compares two arrays of proto3 Value.
   222  func Proto3ValuesEqual(v1, v2 []*querypb.Value) bool {
   223  	if len(v1) != len(v2) {
   224  		return false
   225  	}
   226  	for i, v := range v1 {
   227  		if !proto.Equal(v, v2[i]) {
   228  			return false
   229  		}
   230  	}
   231  	return true
   232  }