github.com/vedadiyan/sqlparser@v1.0.0/pkg/sqltypes/bind_variables.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  	"bytes"
    21  	"errors"
    22  	"fmt"
    23  	"strconv"
    24  
    25  	"google.golang.org/protobuf/proto"
    26  
    27  	querypb "github.com/vedadiyan/sqlparser/pkg/query"
    28  )
    29  
    30  type DecimalFloat float64
    31  
    32  var (
    33  	// BvSchemaName is bind variable to be sent down to vttablet for schema name.
    34  	BvSchemaName = "__vtschemaname"
    35  
    36  	// BvReplaceSchemaName is bind variable to be sent down to vttablet to replace schema name.
    37  	BvReplaceSchemaName = "__replacevtschemaname"
    38  
    39  	// NullBindVariable is a bindvar with NULL value.
    40  	NullBindVariable = &querypb.BindVariable{Type: querypb.Type_NULL_TYPE}
    41  )
    42  
    43  // ValueToProto converts Value to a *querypb.Value.
    44  func ValueToProto(v Value) *querypb.Value {
    45  	return &querypb.Value{Type: v.typ, Value: v.val}
    46  }
    47  
    48  // ProtoToValue converts a *querypb.Value to a Value.
    49  func ProtoToValue(v *querypb.Value) Value {
    50  	return MakeTrusted(v.Type, v.Value)
    51  }
    52  
    53  // BuildBindVariables builds a map[string]*querypb.BindVariable from a map[string]any
    54  func BuildBindVariables(in map[string]any) (map[string]*querypb.BindVariable, error) {
    55  	if len(in) == 0 {
    56  		return nil, nil
    57  	}
    58  
    59  	out := make(map[string]*querypb.BindVariable, len(in))
    60  	for k, v := range in {
    61  		bv, err := BuildBindVariable(v)
    62  		if err != nil {
    63  			return nil, fmt.Errorf("%s: %v", k, err)
    64  		}
    65  		out[k] = bv
    66  	}
    67  	return out, nil
    68  }
    69  
    70  // HexNumBindVariable converts bytes representing a hex number to a bind var.
    71  func HexNumBindVariable(v []byte) *querypb.BindVariable {
    72  	return ValueBindVariable(NewHexNum(v))
    73  }
    74  
    75  // HexValBindVariable converts bytes representing a hex encoded string to a bind var.
    76  func HexValBindVariable(v []byte) *querypb.BindVariable {
    77  	return ValueBindVariable(NewHexVal(v))
    78  }
    79  
    80  // BitNumBindVariable converts bytes representing a bit encoded string to a bind var.
    81  func BitNumBindVariable(v []byte) *querypb.BindVariable {
    82  	return ValueBindVariable(NewBitNum(v))
    83  }
    84  
    85  // Int8BindVariable converts an int8 to a bind var.
    86  func Int8BindVariable(v int8) *querypb.BindVariable {
    87  	return ValueBindVariable(NewInt8(v))
    88  }
    89  
    90  // Int32BindVariable converts an int32 to a bind var.
    91  func Int32BindVariable(v int32) *querypb.BindVariable {
    92  	return ValueBindVariable(NewInt32(v))
    93  }
    94  
    95  // Uint32BindVariable converts a uint32 to a bind var.
    96  func Uint32BindVariable(v uint32) *querypb.BindVariable {
    97  	return ValueBindVariable(NewUint32(v))
    98  }
    99  
   100  // BoolBindVariable converts an bool to a int64 bind var.
   101  func BoolBindVariable(v bool) *querypb.BindVariable {
   102  	if v {
   103  		return Int64BindVariable(1)
   104  	}
   105  	return Int64BindVariable(0)
   106  }
   107  
   108  // Int64BindVariable converts an int64 to a bind var.
   109  func Int64BindVariable(v int64) *querypb.BindVariable {
   110  	return ValueBindVariable(NewInt64(v))
   111  }
   112  
   113  // Uint64BindVariable converts a uint64 to a bind var.
   114  func Uint64BindVariable(v uint64) *querypb.BindVariable {
   115  	return ValueBindVariable(NewUint64(v))
   116  }
   117  
   118  // Float64BindVariable converts a float64 to a bind var.
   119  func Float64BindVariable(v float64) *querypb.BindVariable {
   120  	return ValueBindVariable(NewFloat64(v))
   121  }
   122  
   123  func DecimalBindVariable(v DecimalFloat) *querypb.BindVariable {
   124  	f := strconv.FormatFloat(float64(v), 'f', -1, 64)
   125  	return ValueBindVariable(NewDecimal(f))
   126  }
   127  
   128  // StringBindVariable converts a string to a bind var.
   129  func StringBindVariable(v string) *querypb.BindVariable {
   130  	return ValueBindVariable(NewVarChar(v))
   131  }
   132  
   133  // BytesBindVariable converts a []byte to a bind var.
   134  func BytesBindVariable(v []byte) *querypb.BindVariable {
   135  	return &querypb.BindVariable{Type: VarBinary, Value: v}
   136  }
   137  
   138  // ValueBindVariable converts a Value to a bind var.
   139  func ValueBindVariable(v Value) *querypb.BindVariable {
   140  	return &querypb.BindVariable{Type: v.typ, Value: v.val}
   141  }
   142  
   143  // BuildBindVariable builds a *querypb.BindVariable from a valid input type.
   144  func BuildBindVariable(v any) (*querypb.BindVariable, error) {
   145  	switch v := v.(type) {
   146  	case string:
   147  		return StringBindVariable(v), nil
   148  	case []byte:
   149  		return BytesBindVariable(v), nil
   150  	case bool:
   151  		if v {
   152  			return Int8BindVariable(1), nil
   153  		}
   154  		return Int8BindVariable(0), nil
   155  	case int:
   156  		return &querypb.BindVariable{
   157  			Type:  querypb.Type_INT64,
   158  			Value: strconv.AppendInt(nil, int64(v), 10),
   159  		}, nil
   160  	case uint:
   161  		return &querypb.BindVariable{
   162  			Type:  querypb.Type_UINT64,
   163  			Value: strconv.AppendUint(nil, uint64(v), 10),
   164  		}, nil
   165  	case int32:
   166  		return Int32BindVariable(v), nil
   167  	case uint32:
   168  		return Uint32BindVariable(v), nil
   169  	case int64:
   170  		return Int64BindVariable(v), nil
   171  	case uint64:
   172  		return Uint64BindVariable(v), nil
   173  	case DecimalFloat:
   174  		return DecimalBindVariable(v), nil
   175  	case float64:
   176  		return Float64BindVariable(v), nil
   177  	case nil:
   178  		return NullBindVariable, nil
   179  	case Value:
   180  		return ValueBindVariable(v), nil
   181  	case *querypb.BindVariable:
   182  		return v, nil
   183  	case []any:
   184  		bv := &querypb.BindVariable{
   185  			Type:   querypb.Type_TUPLE,
   186  			Values: make([]*querypb.Value, len(v)),
   187  		}
   188  		values := make([]querypb.Value, len(v))
   189  		for i, lv := range v {
   190  			lbv, err := BuildBindVariable(lv)
   191  			if err != nil {
   192  				return nil, err
   193  			}
   194  			values[i].Type = lbv.Type
   195  			values[i].Value = lbv.Value
   196  			bv.Values[i] = &values[i]
   197  		}
   198  		return bv, nil
   199  	case []string:
   200  		bv := &querypb.BindVariable{
   201  			Type:   querypb.Type_TUPLE,
   202  			Values: make([]*querypb.Value, len(v)),
   203  		}
   204  		values := make([]querypb.Value, len(v))
   205  		for i, lv := range v {
   206  			values[i].Type = querypb.Type_VARCHAR
   207  			values[i].Value = []byte(lv)
   208  			bv.Values[i] = &values[i]
   209  		}
   210  		return bv, nil
   211  	case [][]byte:
   212  		bv := &querypb.BindVariable{
   213  			Type:   querypb.Type_TUPLE,
   214  			Values: make([]*querypb.Value, len(v)),
   215  		}
   216  		values := make([]querypb.Value, len(v))
   217  		for i, lv := range v {
   218  			values[i].Type = querypb.Type_VARBINARY
   219  			values[i].Value = lv
   220  			bv.Values[i] = &values[i]
   221  		}
   222  		return bv, nil
   223  	case []int:
   224  		bv := &querypb.BindVariable{
   225  			Type:   querypb.Type_TUPLE,
   226  			Values: make([]*querypb.Value, len(v)),
   227  		}
   228  		values := make([]querypb.Value, len(v))
   229  		for i, lv := range v {
   230  			values[i].Type = querypb.Type_INT64
   231  			values[i].Value = strconv.AppendInt(nil, int64(lv), 10)
   232  			bv.Values[i] = &values[i]
   233  		}
   234  		return bv, nil
   235  	case []uint:
   236  		bv := &querypb.BindVariable{
   237  			Type:   querypb.Type_TUPLE,
   238  			Values: make([]*querypb.Value, len(v)),
   239  		}
   240  		values := make([]querypb.Value, len(v))
   241  		for i, lv := range v {
   242  			values[i].Type = querypb.Type_UINT64
   243  			values[i].Value = strconv.AppendInt(nil, int64(lv), 10)
   244  			bv.Values[i] = &values[i]
   245  		}
   246  		return bv, nil
   247  	case []int32:
   248  		bv := &querypb.BindVariable{
   249  			Type:   querypb.Type_TUPLE,
   250  			Values: make([]*querypb.Value, len(v)),
   251  		}
   252  		values := make([]querypb.Value, len(v))
   253  		for i, lv := range v {
   254  			values[i].Type = querypb.Type_INT32
   255  			values[i].Value = strconv.AppendInt(nil, int64(lv), 10)
   256  			bv.Values[i] = &values[i]
   257  		}
   258  		return bv, nil
   259  	case []uint32:
   260  		bv := &querypb.BindVariable{
   261  			Type:   querypb.Type_TUPLE,
   262  			Values: make([]*querypb.Value, len(v)),
   263  		}
   264  		values := make([]querypb.Value, len(v))
   265  		for i, lv := range v {
   266  			values[i].Type = querypb.Type_UINT32
   267  			values[i].Value = strconv.AppendUint(nil, uint64(lv), 10)
   268  			bv.Values[i] = &values[i]
   269  		}
   270  		return bv, nil
   271  	case []int64:
   272  		bv := &querypb.BindVariable{
   273  			Type:   querypb.Type_TUPLE,
   274  			Values: make([]*querypb.Value, len(v)),
   275  		}
   276  		values := make([]querypb.Value, len(v))
   277  		for i, lv := range v {
   278  			values[i].Type = querypb.Type_INT64
   279  			values[i].Value = strconv.AppendInt(nil, lv, 10)
   280  			bv.Values[i] = &values[i]
   281  		}
   282  		return bv, nil
   283  	case []uint64:
   284  		bv := &querypb.BindVariable{
   285  			Type:   querypb.Type_TUPLE,
   286  			Values: make([]*querypb.Value, len(v)),
   287  		}
   288  		values := make([]querypb.Value, len(v))
   289  		for i, lv := range v {
   290  			values[i].Type = querypb.Type_UINT64
   291  			values[i].Value = strconv.AppendUint(nil, lv, 10)
   292  			bv.Values[i] = &values[i]
   293  		}
   294  		return bv, nil
   295  	case []float64:
   296  		bv := &querypb.BindVariable{
   297  			Type:   querypb.Type_TUPLE,
   298  			Values: make([]*querypb.Value, len(v)),
   299  		}
   300  		values := make([]querypb.Value, len(v))
   301  		for i, lv := range v {
   302  			values[i].Type = querypb.Type_FLOAT64
   303  			values[i].Value = strconv.AppendFloat(nil, lv, 'g', -1, 64)
   304  			bv.Values[i] = &values[i]
   305  		}
   306  		return bv, nil
   307  	case []Value:
   308  		bv := &querypb.BindVariable{
   309  			Type:   querypb.Type_TUPLE,
   310  			Values: make([]*querypb.Value, len(v)),
   311  		}
   312  		values := make([]querypb.Value, len(v))
   313  		for i, lv := range v {
   314  			lbv, err := BuildBindVariable(lv)
   315  			if err != nil {
   316  				return nil, err
   317  			}
   318  			values[i].Type = lbv.Type
   319  			values[i].Value = lbv.Value
   320  			bv.Values[i] = &values[i]
   321  		}
   322  		return bv, nil
   323  	}
   324  	return nil, fmt.Errorf("type %T not supported as bind var: %v", v, v)
   325  }
   326  
   327  // ValidateBindVariables validates a map[string]*querypb.BindVariable.
   328  func ValidateBindVariables(bv map[string]*querypb.BindVariable) error {
   329  	for k, v := range bv {
   330  		if err := ValidateBindVariable(v); err != nil {
   331  			return fmt.Errorf("%s: %v", k, err)
   332  		}
   333  	}
   334  	return nil
   335  }
   336  
   337  // ValidateBindVariable returns an error if the bind variable has inconsistent
   338  // fields.
   339  func ValidateBindVariable(bv *querypb.BindVariable) error {
   340  	if bv == nil {
   341  		return errors.New("bind variable is nil")
   342  	}
   343  
   344  	if bv.Type == querypb.Type_TUPLE {
   345  		if len(bv.Values) == 0 {
   346  			return errors.New("empty tuple is not allowed")
   347  		}
   348  		for _, val := range bv.Values {
   349  			if val.Type == querypb.Type_TUPLE {
   350  				return errors.New("tuple not allowed inside another tuple")
   351  			}
   352  			if err := ValidateBindVariable(&querypb.BindVariable{Type: val.Type, Value: val.Value}); err != nil {
   353  				return err
   354  			}
   355  		}
   356  		return nil
   357  	}
   358  
   359  	// If NewValue succeeds, the value is valid.
   360  	_, err := NewValue(bv.Type, bv.Value)
   361  	return err
   362  }
   363  
   364  // BindVariableToValue converts a bind var into a Value.
   365  func BindVariableToValue(bv *querypb.BindVariable) (Value, error) {
   366  	if bv.Type == querypb.Type_TUPLE {
   367  		return NULL, errors.New("cannot convert a TUPLE bind var into a value")
   368  	}
   369  	return MakeTrusted(bv.Type, bv.Value), nil
   370  }
   371  
   372  // BindVariablesEqual compares two maps of bind variables.
   373  // For protobuf messages we have to use "proto.Equal".
   374  func BindVariablesEqual(x, y map[string]*querypb.BindVariable) bool {
   375  	return proto.Equal(&querypb.BoundQuery{BindVariables: x}, &querypb.BoundQuery{BindVariables: y})
   376  }
   377  
   378  // CopyBindVariables returns a shallow-copy of the given bindVariables map.
   379  func CopyBindVariables(bindVariables map[string]*querypb.BindVariable) map[string]*querypb.BindVariable {
   380  	result := make(map[string]*querypb.BindVariable, len(bindVariables))
   381  	for key, value := range bindVariables {
   382  		result[key] = value
   383  	}
   384  	return result
   385  }
   386  
   387  // FormatBindVariables returns a string representation of the
   388  // bind variables.
   389  //
   390  // If full is false, then large string or tuple values are truncated
   391  // to only print the lengths.
   392  //
   393  // If asJson is true, then the resulting string is a valid JSON
   394  // representation, otherwise it is the golang printed map representation.
   395  func FormatBindVariables(bindVariables map[string]*querypb.BindVariable, full, asJSON bool) string {
   396  	var out map[string]*querypb.BindVariable
   397  	if full {
   398  		out = bindVariables
   399  	} else {
   400  		// NOTE(szopa): I am getting rid of potentially large bind
   401  		// variables.
   402  		out = make(map[string]*querypb.BindVariable)
   403  		for k, v := range bindVariables {
   404  			if IsIntegral(v.Type) || IsFloat(v.Type) {
   405  				out[k] = v
   406  			} else if v.Type == querypb.Type_TUPLE {
   407  				out[k] = StringBindVariable(fmt.Sprintf("%v items", len(v.Values)))
   408  			} else {
   409  				out[k] = StringBindVariable(fmt.Sprintf("%v bytes", len(v.Value)))
   410  			}
   411  		}
   412  	}
   413  
   414  	if asJSON {
   415  		var buf bytes.Buffer
   416  		buf.WriteString("{")
   417  		first := true
   418  		for k, v := range out {
   419  			if !first {
   420  				buf.WriteString(", ")
   421  			} else {
   422  				first = false
   423  			}
   424  			if IsIntegral(v.Type) || IsFloat(v.Type) {
   425  				fmt.Fprintf(&buf, "%q: {\"type\": %q, \"value\": %v}", k, v.Type, string(v.Value))
   426  			} else {
   427  				fmt.Fprintf(&buf, "%q: {\"type\": %q, \"value\": %q}", k, v.Type, string(v.Value))
   428  			}
   429  		}
   430  		buf.WriteString("}")
   431  		return buf.String()
   432  	}
   433  
   434  	return fmt.Sprintf("%v", out)
   435  }