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 }