github.com/tsuna/gohbase@v0.0.0-20250731002811-4ffcadfba63e/hrpc/query.go (about)

     1  // Copyright (C) 2017  The GoHBase Authors.  All rights reserved.
     2  // This file is part of GoHBase.
     3  // Use of this source code is governed by the Apache License 2.0
     4  // that can be found in the COPYING file.
     5  
     6  package hrpc
     7  
     8  import (
     9  	"errors"
    10  	"math"
    11  	"time"
    12  
    13  	"github.com/tsuna/gohbase/filter"
    14  	"github.com/tsuna/gohbase/pb"
    15  )
    16  
    17  // baseQuery bundles common fields that can be provided for quering requests: Scans and Gets
    18  type baseQuery struct {
    19  	families      map[string][]string
    20  	filter        *pb.Filter
    21  	fromTimestamp uint64
    22  	toTimestamp   uint64
    23  	maxVersions   uint32
    24  	storeLimit    uint32
    25  	storeOffset   uint32
    26  	priority      uint32
    27  	cacheBlocks   bool
    28  	consistency   ConsistencyType
    29  }
    30  
    31  // ConsistencyType is used to specify the required consistency of data
    32  //
    33  // See https://docs.cloudera.com/HDPDocuments/HDP2/HDP-2.2.9/bk_hadoop-ha/
    34  //
    35  //	content/ha-hbase-timeline-consistency.html
    36  type ConsistencyType int
    37  
    38  const (
    39  	// Use HBase's default
    40  	DefaultConsistency ConsistencyType = iota
    41  
    42  	// Guarantees that the client receives the latest data.
    43  	StrongConsistency
    44  
    45  	// Client might receive stale data (indicated by the Stale field), but
    46  	// the data that is received was valid at a given point of time.
    47  	TimelineConsistency
    48  )
    49  
    50  func (c ConsistencyType) toProto() (ret *pb.Consistency) {
    51  	ret = new(pb.Consistency)
    52  	switch c {
    53  	case TimelineConsistency:
    54  		*ret = pb.Consistency_TIMELINE
    55  		return
    56  	case StrongConsistency:
    57  		*ret = pb.Consistency_STRONG
    58  		return
    59  	case DefaultConsistency:
    60  		panic("default consistency depends on context")
    61  	}
    62  	panic("invalid value for ConsistencyType")
    63  }
    64  
    65  // newBaseQuery return baseQuery with all default values
    66  func newBaseQuery() baseQuery {
    67  	return baseQuery{
    68  		storeLimit:    DefaultMaxResultsPerColumnFamily,
    69  		fromTimestamp: MinTimestamp,
    70  		toTimestamp:   MaxTimestamp,
    71  		maxVersions:   DefaultMaxVersions,
    72  		cacheBlocks:   DefaultCacheBlocks,
    73  	}
    74  }
    75  
    76  func (bq *baseQuery) setFamilies(families map[string][]string) {
    77  	bq.families = families
    78  }
    79  func (bq *baseQuery) setFilter(filter *pb.Filter) {
    80  	bq.filter = filter
    81  }
    82  func (bq *baseQuery) setTimeRangeUint64(from, to uint64) {
    83  	bq.fromTimestamp = from
    84  	bq.toTimestamp = to
    85  }
    86  func (bq *baseQuery) setMaxVersions(versions uint32) {
    87  	bq.maxVersions = versions
    88  }
    89  func (bq *baseQuery) setMaxResultsPerColumnFamily(maxresults uint32) {
    90  	bq.storeLimit = maxresults
    91  }
    92  func (bq *baseQuery) setResultOffset(offset uint32) {
    93  	bq.storeOffset = offset
    94  }
    95  func (bq *baseQuery) setCacheBlocks(cacheBlocks bool) {
    96  	bq.cacheBlocks = cacheBlocks
    97  }
    98  func (bq *baseQuery) setConsistency(consistency ConsistencyType) {
    99  	bq.consistency = consistency
   100  }
   101  func (bq *baseQuery) setPriority(priority uint32) {
   102  	bq.priority = priority
   103  }
   104  func (bq *baseQuery) Priority() uint32 {
   105  	return bq.priority
   106  }
   107  
   108  // GetPriority returns the priority of a Call. Returns 0 for calls
   109  // that don't have a priority set or don't support setting a priority.
   110  func GetPriority(c Call) uint32 {
   111  	p, ok := c.(interface{ Priority() uint32 })
   112  	if !ok {
   113  		return 0
   114  	}
   115  	return p.Priority()
   116  }
   117  
   118  // Families option adds families constraint to a Scan or Get request.
   119  func Families(f map[string][]string) func(Call) error {
   120  	return func(hc Call) error {
   121  		if c, ok := hc.(hasQueryOptions); ok {
   122  			c.setFamilies(f)
   123  			return nil
   124  		}
   125  		return errors.New("'Families' option can only be used with Get or Scan request")
   126  	}
   127  }
   128  
   129  // Filters option adds filters constraint to a Scan or Get request.
   130  func Filters(f filter.Filter) func(Call) error {
   131  	return func(hc Call) error {
   132  		if c, ok := hc.(hasQueryOptions); ok {
   133  			pbF, err := f.ConstructPBFilter()
   134  			if err != nil {
   135  				return err
   136  			}
   137  			c.setFilter(pbF)
   138  			return nil
   139  		}
   140  		return errors.New("'Filters' option can only be used with Get or Scan request")
   141  	}
   142  }
   143  
   144  // TimeRange is used as a parameter for request creation. Adds TimeRange constraint to a request.
   145  // It will get values in range [from, to[ ('to' is exclusive).
   146  func TimeRange(from, to time.Time) func(Call) error {
   147  	return TimeRangeUint64(uint64(from.UnixNano()/1e6), uint64(to.UnixNano()/1e6))
   148  }
   149  
   150  // TimeRangeUint64 is used as a parameter for request creation.
   151  // Adds TimeRange constraint to a request.
   152  // from and to should be in milliseconds
   153  // // It will get values in range [from, to[ ('to' is exclusive).
   154  func TimeRangeUint64(from, to uint64) func(Call) error {
   155  	return func(hc Call) error {
   156  		if c, ok := hc.(hasQueryOptions); ok {
   157  			if from >= to {
   158  				// or equal is becuase 'to' is exclusive
   159  				return errors.New("'from' timestamp is greater or equal to 'to' timestamp")
   160  			}
   161  			c.setTimeRangeUint64(from, to)
   162  			return nil
   163  		}
   164  		return errors.New("'TimeRange' option can only be used with Get or Scan request")
   165  	}
   166  }
   167  
   168  // MaxVersions is used as a parameter for request creation.
   169  // Adds MaxVersions constraint to a request.
   170  func MaxVersions(versions uint32) func(Call) error {
   171  	return func(hc Call) error {
   172  		if c, ok := hc.(hasQueryOptions); ok {
   173  			if versions > math.MaxInt32 {
   174  				return errors.New("'MaxVersions' exceeds supported number of versions")
   175  			}
   176  			c.setMaxVersions(versions)
   177  			return nil
   178  		}
   179  		return errors.New("'MaxVersions' option can only be used with Get or Scan request")
   180  	}
   181  }
   182  
   183  // MaxResultsPerColumnFamily is an option for Get or Scan requests that sets the maximum
   184  // number of cells returned per column family in a row.
   185  func MaxResultsPerColumnFamily(maxresults uint32) func(Call) error {
   186  	return func(hc Call) error {
   187  		if c, ok := hc.(hasQueryOptions); ok {
   188  			if maxresults > math.MaxInt32 {
   189  				return errors.New(
   190  					"'MaxResultsPerColumnFamily' exceeds supported number of value results")
   191  			}
   192  			c.setMaxResultsPerColumnFamily(maxresults)
   193  			return nil
   194  		}
   195  		return errors.New(
   196  			"'MaxResultsPerColumnFamily' option can only be used with Get or Scan request")
   197  	}
   198  }
   199  
   200  // ResultOffset is a option for Scan or Get requests that sets the offset for cells
   201  // within a column family.
   202  func ResultOffset(offset uint32) func(Call) error {
   203  	return func(hc Call) error {
   204  		if c, ok := hc.(hasQueryOptions); ok {
   205  			if offset > math.MaxInt32 {
   206  				return errors.New("'ResultOffset' exceeds supported offset value")
   207  			}
   208  			c.setResultOffset(offset)
   209  			return nil
   210  		}
   211  		return errors.New("'ResultOffset' option can only be used with Get or Scan request")
   212  	}
   213  }
   214  
   215  // CacheBlocks is an option for Scan or Get requests to enable/disable the block cache
   216  // for the request
   217  func CacheBlocks(cacheBlocks bool) func(Call) error {
   218  	return func(hc Call) error {
   219  		if c, ok := hc.(hasQueryOptions); ok {
   220  			c.setCacheBlocks(cacheBlocks)
   221  			return nil
   222  		}
   223  		return errors.New("'CacheBlocks' option can only be used with Get or Scan request")
   224  	}
   225  }
   226  
   227  // Consistency is a Scan or Get option that requests the given
   228  // consistency of data.
   229  func Consistency(consistency ConsistencyType) func(Call) error {
   230  	return func(g Call) error {
   231  		if c, ok := g.(hasQueryOptions); ok {
   232  			c.setConsistency(consistency)
   233  			return nil
   234  		}
   235  		return errors.New("'Consistency' option can only be used with Get or Scan requests")
   236  	}
   237  }
   238  
   239  func Priority(priority uint32) func(Call) error {
   240  	return func(hc Call) error {
   241  		if c, ok := hc.(hasQueryOptions); ok {
   242  			c.setPriority(priority)
   243  			return nil
   244  		}
   245  		return errors.New("'Priority' option can only be used with Get or Scan requests")
   246  	}
   247  }