github.com/vedadiyan/sqlparser@v1.0.0/pkg/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/vedadiyan/sqlparser/pkg/vterrors"
    23  
    24  	querypb "github.com/vedadiyan/sqlparser/pkg/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  		Info:                qr.Info,
   108  		SessionStateChanges: qr.SessionStateChanges,
   109  	}
   110  }
   111  
   112  // Proto3ToResult converts a proto3 Result to an internal data structure. This function
   113  // should be used only if the field info is populated in qr.
   114  func Proto3ToResult(qr *querypb.QueryResult) *Result {
   115  	if qr == nil {
   116  		return nil
   117  	}
   118  	return &Result{
   119  		Fields:              qr.Fields,
   120  		RowsAffected:        qr.RowsAffected,
   121  		InsertID:            qr.InsertId,
   122  		Rows:                proto3ToRows(qr.Fields, qr.Rows),
   123  		Info:                qr.Info,
   124  		SessionStateChanges: qr.SessionStateChanges,
   125  	}
   126  }
   127  
   128  // CustomProto3ToResult converts a proto3 Result to an internal data structure. This function
   129  // takes a separate fields input because not all QueryResults contain the field info.
   130  // In particular, only the first packet of streaming queries contain the field info.
   131  func CustomProto3ToResult(fields []*querypb.Field, qr *querypb.QueryResult) *Result {
   132  	if qr == nil {
   133  		return nil
   134  	}
   135  	return &Result{
   136  		Fields:              qr.Fields,
   137  		RowsAffected:        qr.RowsAffected,
   138  		InsertID:            qr.InsertId,
   139  		Rows:                proto3ToRows(fields, qr.Rows),
   140  		Info:                qr.Info,
   141  		SessionStateChanges: qr.SessionStateChanges,
   142  	}
   143  }
   144  
   145  // ResultsToProto3 converts []Result to proto3.
   146  func ResultsToProto3(qr []Result) []*querypb.QueryResult {
   147  	if len(qr) == 0 {
   148  		return nil
   149  	}
   150  	result := make([]*querypb.QueryResult, len(qr))
   151  	for i, q := range qr {
   152  		result[i] = ResultToProto3(&q)
   153  	}
   154  	return result
   155  }
   156  
   157  // Proto3ToResults converts proto3 results to []Result.
   158  func Proto3ToResults(qr []*querypb.QueryResult) []Result {
   159  	if len(qr) == 0 {
   160  		return nil
   161  	}
   162  	result := make([]Result, len(qr))
   163  	for i, q := range qr {
   164  		result[i] = *Proto3ToResult(q)
   165  	}
   166  	return result
   167  }
   168  
   169  // QueryResponsesToProto3 converts []QueryResponse to proto3.
   170  func QueryResponsesToProto3(qr []QueryResponse) []*querypb.ResultWithError {
   171  	if len(qr) == 0 {
   172  		return nil
   173  	}
   174  	result := make([]*querypb.ResultWithError, len(qr))
   175  	for i, q := range qr {
   176  		result[i] = &querypb.ResultWithError{
   177  			Result: ResultToProto3(q.QueryResult),
   178  			Error:  vterrors.ToVTRPC(q.QueryError),
   179  		}
   180  	}
   181  	return result
   182  }
   183  
   184  // Proto3ToQueryReponses converts proto3 queryResponse to []QueryResponse.
   185  func Proto3ToQueryReponses(qr []*querypb.ResultWithError) []QueryResponse {
   186  	if len(qr) == 0 {
   187  		return nil
   188  	}
   189  	result := make([]QueryResponse, len(qr))
   190  	for i, q := range qr {
   191  		result[i] = QueryResponse{
   192  			QueryResult: Proto3ToResult(q.Result),
   193  			QueryError:  vterrors.FromVTRPC(q.Error),
   194  		}
   195  	}
   196  	return result
   197  }
   198  
   199  // Proto3ResultsEqual compares two arrays of proto3 Result.
   200  // reflect.DeepEqual shouldn't be used because of the protos.
   201  func Proto3ResultsEqual(r1, r2 []*querypb.QueryResult) bool {
   202  	if len(r1) != len(r2) {
   203  		return false
   204  	}
   205  	for i, r := range r1 {
   206  		if !proto.Equal(r, r2[i]) {
   207  			return false
   208  		}
   209  	}
   210  	return true
   211  }
   212  
   213  // Proto3QueryResponsesEqual compares two arrays of proto3 QueryResponse.
   214  // reflect.DeepEqual shouldn't be used because of the protos.
   215  func Proto3QueryResponsesEqual(r1, r2 []*querypb.ResultWithError) bool {
   216  	if len(r1) != len(r2) {
   217  		return false
   218  	}
   219  	for i, r := range r1 {
   220  		if !proto.Equal(r, r2[i]) {
   221  			return false
   222  		}
   223  	}
   224  	return true
   225  }
   226  
   227  // Proto3ValuesEqual compares two arrays of proto3 Value.
   228  func Proto3ValuesEqual(v1, v2 []*querypb.Value) bool {
   229  	if len(v1) != len(v2) {
   230  		return false
   231  	}
   232  	for i, v := range v1 {
   233  		if !proto.Equal(v, v2[i]) {
   234  			return false
   235  		}
   236  	}
   237  	return true
   238  }