...

Source file src/github.com/jackc/pgx/v5/pgtype/range.go

Documentation: github.com/jackc/pgx/v5/pgtype

     1  package pgtype
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  )
     8  
     9  type BoundType byte
    10  
    11  const (
    12  	Inclusive = BoundType('i')
    13  	Exclusive = BoundType('e')
    14  	Unbounded = BoundType('U')
    15  	Empty     = BoundType('E')
    16  )
    17  
    18  func (bt BoundType) String() string {
    19  	return string(bt)
    20  }
    21  
    22  type untypedTextRange struct {
    23  	Lower     string
    24  	Upper     string
    25  	LowerType BoundType
    26  	UpperType BoundType
    27  }
    28  
    29  func parseUntypedTextRange(src string) (*untypedTextRange, error) {
    30  	utr := &untypedTextRange{}
    31  	if src == "empty" {
    32  		utr.LowerType = Empty
    33  		utr.UpperType = Empty
    34  		return utr, nil
    35  	}
    36  
    37  	buf := bytes.NewBufferString(src)
    38  
    39  	skipWhitespace(buf)
    40  
    41  	r, _, err := buf.ReadRune()
    42  	if err != nil {
    43  		return nil, fmt.Errorf("invalid lower bound: %w", err)
    44  	}
    45  	switch r {
    46  	case '(':
    47  		utr.LowerType = Exclusive
    48  	case '[':
    49  		utr.LowerType = Inclusive
    50  	default:
    51  		return nil, fmt.Errorf("missing lower bound, instead got: %v", string(r))
    52  	}
    53  
    54  	r, _, err = buf.ReadRune()
    55  	if err != nil {
    56  		return nil, fmt.Errorf("invalid lower value: %w", err)
    57  	}
    58  	buf.UnreadRune()
    59  
    60  	if r == ',' {
    61  		utr.LowerType = Unbounded
    62  	} else {
    63  		utr.Lower, err = rangeParseValue(buf)
    64  		if err != nil {
    65  			return nil, fmt.Errorf("invalid lower value: %w", err)
    66  		}
    67  	}
    68  
    69  	r, _, err = buf.ReadRune()
    70  	if err != nil {
    71  		return nil, fmt.Errorf("missing range separator: %w", err)
    72  	}
    73  	if r != ',' {
    74  		return nil, fmt.Errorf("missing range separator: %v", r)
    75  	}
    76  
    77  	r, _, err = buf.ReadRune()
    78  	if err != nil {
    79  		return nil, fmt.Errorf("invalid upper value: %w", err)
    80  	}
    81  
    82  	if r == ')' || r == ']' {
    83  		utr.UpperType = Unbounded
    84  	} else {
    85  		buf.UnreadRune()
    86  		utr.Upper, err = rangeParseValue(buf)
    87  		if err != nil {
    88  			return nil, fmt.Errorf("invalid upper value: %w", err)
    89  		}
    90  
    91  		r, _, err = buf.ReadRune()
    92  		if err != nil {
    93  			return nil, fmt.Errorf("missing upper bound: %w", err)
    94  		}
    95  		switch r {
    96  		case ')':
    97  			utr.UpperType = Exclusive
    98  		case ']':
    99  			utr.UpperType = Inclusive
   100  		default:
   101  			return nil, fmt.Errorf("missing upper bound, instead got: %v", string(r))
   102  		}
   103  	}
   104  
   105  	skipWhitespace(buf)
   106  
   107  	if buf.Len() > 0 {
   108  		return nil, fmt.Errorf("unexpected trailing data: %v", buf.String())
   109  	}
   110  
   111  	return utr, nil
   112  }
   113  
   114  func rangeParseValue(buf *bytes.Buffer) (string, error) {
   115  	r, _, err := buf.ReadRune()
   116  	if err != nil {
   117  		return "", err
   118  	}
   119  	if r == '"' {
   120  		return rangeParseQuotedValue(buf)
   121  	}
   122  	buf.UnreadRune()
   123  
   124  	s := &bytes.Buffer{}
   125  
   126  	for {
   127  		r, _, err := buf.ReadRune()
   128  		if err != nil {
   129  			return "", err
   130  		}
   131  
   132  		switch r {
   133  		case '\\':
   134  			r, _, err = buf.ReadRune()
   135  			if err != nil {
   136  				return "", err
   137  			}
   138  		case ',', '[', ']', '(', ')':
   139  			buf.UnreadRune()
   140  			return s.String(), nil
   141  		}
   142  
   143  		s.WriteRune(r)
   144  	}
   145  }
   146  
   147  func rangeParseQuotedValue(buf *bytes.Buffer) (string, error) {
   148  	s := &bytes.Buffer{}
   149  
   150  	for {
   151  		r, _, err := buf.ReadRune()
   152  		if err != nil {
   153  			return "", err
   154  		}
   155  
   156  		switch r {
   157  		case '\\':
   158  			r, _, err = buf.ReadRune()
   159  			if err != nil {
   160  				return "", err
   161  			}
   162  		case '"':
   163  			r, _, err = buf.ReadRune()
   164  			if err != nil {
   165  				return "", err
   166  			}
   167  			if r != '"' {
   168  				buf.UnreadRune()
   169  				return s.String(), nil
   170  			}
   171  		}
   172  		s.WriteRune(r)
   173  	}
   174  }
   175  
   176  type untypedBinaryRange struct {
   177  	Lower     []byte
   178  	Upper     []byte
   179  	LowerType BoundType
   180  	UpperType BoundType
   181  }
   182  
   183  // 0 = ()      = 00000
   184  // 1 = empty   = 00001
   185  // 2 = [)      = 00010
   186  // 4 = (]      = 00100
   187  // 6 = []      = 00110
   188  // 8 = )       = 01000
   189  // 12 = ]      = 01100
   190  // 16 = (      = 10000
   191  // 18 = [      = 10010
   192  // 24 =        = 11000
   193  
   194  const emptyMask = 1
   195  const lowerInclusiveMask = 2
   196  const upperInclusiveMask = 4
   197  const lowerUnboundedMask = 8
   198  const upperUnboundedMask = 16
   199  
   200  func parseUntypedBinaryRange(src []byte) (*untypedBinaryRange, error) {
   201  	ubr := &untypedBinaryRange{}
   202  
   203  	if len(src) == 0 {
   204  		return nil, fmt.Errorf("range too short: %v", len(src))
   205  	}
   206  
   207  	rangeType := src[0]
   208  	rp := 1
   209  
   210  	if rangeType&emptyMask > 0 {
   211  		if len(src[rp:]) > 0 {
   212  			return nil, fmt.Errorf("unexpected trailing bytes parsing empty range: %v", len(src[rp:]))
   213  		}
   214  		ubr.LowerType = Empty
   215  		ubr.UpperType = Empty
   216  		return ubr, nil
   217  	}
   218  
   219  	if rangeType&lowerInclusiveMask > 0 {
   220  		ubr.LowerType = Inclusive
   221  	} else if rangeType&lowerUnboundedMask > 0 {
   222  		ubr.LowerType = Unbounded
   223  	} else {
   224  		ubr.LowerType = Exclusive
   225  	}
   226  
   227  	if rangeType&upperInclusiveMask > 0 {
   228  		ubr.UpperType = Inclusive
   229  	} else if rangeType&upperUnboundedMask > 0 {
   230  		ubr.UpperType = Unbounded
   231  	} else {
   232  		ubr.UpperType = Exclusive
   233  	}
   234  
   235  	if ubr.LowerType == Unbounded && ubr.UpperType == Unbounded {
   236  		if len(src[rp:]) > 0 {
   237  			return nil, fmt.Errorf("unexpected trailing bytes parsing unbounded range: %v", len(src[rp:]))
   238  		}
   239  		return ubr, nil
   240  	}
   241  
   242  	if len(src[rp:]) < 4 {
   243  		return nil, fmt.Errorf("too few bytes for size: %v", src[rp:])
   244  	}
   245  	valueLen := int(binary.BigEndian.Uint32(src[rp:]))
   246  	rp += 4
   247  
   248  	val := src[rp : rp+valueLen]
   249  	rp += valueLen
   250  
   251  	if ubr.LowerType != Unbounded {
   252  		ubr.Lower = val
   253  	} else {
   254  		ubr.Upper = val
   255  		if len(src[rp:]) > 0 {
   256  			return nil, fmt.Errorf("unexpected trailing bytes parsing range: %v", len(src[rp:]))
   257  		}
   258  		return ubr, nil
   259  	}
   260  
   261  	if ubr.UpperType != Unbounded {
   262  		if len(src[rp:]) < 4 {
   263  			return nil, fmt.Errorf("too few bytes for size: %v", src[rp:])
   264  		}
   265  		valueLen := int(binary.BigEndian.Uint32(src[rp:]))
   266  		rp += 4
   267  		ubr.Upper = src[rp : rp+valueLen]
   268  		rp += valueLen
   269  	}
   270  
   271  	if len(src[rp:]) > 0 {
   272  		return nil, fmt.Errorf("unexpected trailing bytes parsing range: %v", len(src[rp:]))
   273  	}
   274  
   275  	return ubr, nil
   276  
   277  }
   278  
   279  // Range is a generic range type.
   280  type Range[T any] struct {
   281  	Lower     T
   282  	Upper     T
   283  	LowerType BoundType
   284  	UpperType BoundType
   285  	Valid     bool
   286  }
   287  
   288  func (r Range[T]) IsNull() bool {
   289  	return !r.Valid
   290  }
   291  
   292  func (r Range[T]) BoundTypes() (lower, upper BoundType) {
   293  	return r.LowerType, r.UpperType
   294  }
   295  
   296  func (r Range[T]) Bounds() (lower, upper any) {
   297  	return &r.Lower, &r.Upper
   298  }
   299  
   300  func (r *Range[T]) ScanNull() error {
   301  	*r = Range[T]{}
   302  	return nil
   303  }
   304  
   305  func (r *Range[T]) ScanBounds() (lowerTarget, upperTarget any) {
   306  	return &r.Lower, &r.Upper
   307  }
   308  
   309  func (r *Range[T]) SetBoundTypes(lower, upper BoundType) error {
   310  	if lower == Unbounded || lower == Empty {
   311  		var zero T
   312  		r.Lower = zero
   313  	}
   314  	if upper == Unbounded || upper == Empty {
   315  		var zero T
   316  		r.Upper = zero
   317  	}
   318  	r.LowerType = lower
   319  	r.UpperType = upper
   320  	r.Valid = true
   321  	return nil
   322  }
   323  

View as plain text