forked from vanadium-archive/go.v23
-
Notifications
You must be signed in to change notification settings - Fork 0
/
model.go
146 lines (127 loc) · 5.55 KB
/
model.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package datasource defines the interfaces a system must implement to support
// querying.
//
// The Database interface is used to get Table interfaces (by name).
// The Table interface is used to get a KeyValueStream (by key prefixes).
// The KeyValueStream interface is used to iterate over key-value pairs from a
// table.
// Note: Order, Index, GetIndexFields and the indexRanges arg to Scan
// are being provided in beta form for use by discovery. Currently only
// indexes of type string are supported and an index must comprise exactly
// one column. This API will change when secondary indexes are fully supported.
package datasource
import (
"fmt"
"v.io/v23/context"
"v.io/v23/vdl"
"v.io/v23/vom"
)
type Database interface {
// GetContext returns a context (used for creating error messages).
GetContext() *context.T
// GetTable returns an instance of the Table inteface for the table
// specified by name. If writeAccessReq is true, the Table needs
// to support the Delete function. If it cannot, the syncql.NotWritable
// error should be returned.
GetTable(name string, writeAccessReq bool) (Table, error)
}
type Table interface {
// Return the fields on which there exist secondary indexes.
// The possible ranges for these fields will be passed to Scan.
// Example:
// return []datasource.Index{
// datasource.Index{FieldName: "v.InterfaceName", Kind: vdl.String},
// datasource.Index{FieldName: "v.Address", Kind: vdl.String},
// }
// At present, the Kind MUST BE vdl.String
GetIndexFields() []Index
// Return a KeyValueStream where all k/v pairs fall within the range
// of the index ranges passed in (the first of which is for the key).
// Note: an empty string prefix (""), matches all keys.
// The index ranges will be sorted (low to high). The first index range
// will be for the key. After that will be ranges for any index returned
// from GetIndexFields. These will be returned in the same order as was
// present in the return value for GetIndexFields. Currently, only string indexes are
// supported. Index ranges include the index field name (in order to differentiate among
// multiple secondary indexes). Again, the first will always be the "k" field.
// If NilAllowed is true, nil values for the index field should be included in the
// return k/v pairs from Scan. If false, they should not be included.
// It's best to honor all index ranges. The datasource should honor the
// the ranges by not passing in k/v pairs that the ranges exclude. Future
// optimzation may cause incorrect answers if this contract is not kept.
Scan(indexRanges ...IndexRanges) (KeyValueStream, error)
// Delete deletes the k/v pair for key k.
// This will only be called if GetTable was called with writeAccessReq == true.
// If Delete is not supported, GetTable should have returned an error. If
// Delete is called anyway (logic error), the syncql.OperationNotSupported error
// should be returned.
Delete(k string) (bool, error)
}
type KeyValueStream interface {
// Advance stages an element so the client can retrieve it
// with KeyValue. Advance returns true iff there is an
// element to retrieve. The client must call Advance before
// calling KeyValue. The client must call Cancel if it does
// not iterate through all elements (i.e. until Advance
// returns false). Advance may block if an element is not
// immediately available.
Advance() bool
// KeyValue returns the element that was staged by Advance.
// KeyValue may panic if Advance returned false or was not
// called at all. KeyValue does not block.
KeyValue() (string, *vom.RawBytes)
// Err returns a non-nil error iff the stream encountered
// any errors. Err does not block.
Err() error
// Cancel notifies the stream provider that it can stop
// producing elements. The client must call Cancel if it does
// not iterate through all elements (i.e. until Advance
// returns false). Cancel is idempotent and can be called
// concurrently with a goroutine that is iterating via
// Advance/Value. Cancel causes Advance to subsequently
// return false. Cancel does not block.
Cancel()
}
// Implement sort interface for StringFieldRanges.
func (stringFieldRanges StringFieldRanges) Len() int {
return len(stringFieldRanges)
}
func (stringFieldRanges StringFieldRanges) Less(i, j int) bool {
return stringFieldRanges[i].Start < stringFieldRanges[j].Start
}
func (stringFieldRanges StringFieldRanges) Swap(i, j int) {
saveStart := stringFieldRanges[i].Start
saveLimit := stringFieldRanges[i].Limit
stringFieldRanges[i].Start = stringFieldRanges[j].Start
stringFieldRanges[i].Limit = stringFieldRanges[j].Limit
stringFieldRanges[j].Start = saveStart
stringFieldRanges[j].Limit = saveLimit
}
type StringFieldRange struct {
Start string
Limit string
}
type Index struct {
FieldName string
Kind vdl.Kind
}
type StringFieldRanges []StringFieldRange
type IndexRanges struct {
FieldName string
Kind vdl.Kind
NilAllowed bool // true if query could be true for a nil index value
StringRanges *StringFieldRanges
// TODO(jkline): add fields for other types of indexes.
}
// String() used in tests.
func (ir *IndexRanges) String() string {
str := fmt.Sprintf("IndexRanges{FieldName: %s, Kind: %v, NilAllowed: %v, ", ir.FieldName, ir.Kind, ir.NilAllowed)
for _, r := range *ir.StringRanges {
str += fmt.Sprintf("{%s,%s}", r.Start, r.Limit)
}
str += "}"
return str
}