Skip to content

Commit 38e5a36

Browse files
authored
[Feature] Query ForceOneShardAttributeValue (#327)
1 parent 63cef00 commit 38e5a36

File tree

2 files changed

+62
-10
lines changed

2 files changed

+62
-10
lines changed

query.go

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,17 @@ import (
2828
)
2929

3030
const (
31-
keyQueryCount = "arangodb-query-count"
32-
keyQueryBatchSize = "arangodb-query-batchSize"
33-
keyQueryCache = "arangodb-query-cache"
34-
keyQueryMemoryLimit = "arangodb-query-memoryLimit"
35-
keyQueryTTL = "arangodb-query-ttl"
36-
keyQueryOptSatSyncWait = "arangodb-query-opt-satSyncWait"
37-
keyQueryOptFullCount = "arangodb-query-opt-fullCount"
38-
keyQueryOptStream = "arangodb-query-opt-stream"
39-
keyQueryOptProfile = "arangodb-query-opt-profile"
40-
keyQueryOptMaxRuntime = "arangodb-query-opt-maxRuntime"
31+
keyQueryCount = "arangodb-query-count"
32+
keyQueryBatchSize = "arangodb-query-batchSize"
33+
keyQueryCache = "arangodb-query-cache"
34+
keyQueryMemoryLimit = "arangodb-query-memoryLimit"
35+
keyQueryForceOneShardAttributeValue = "arangodb-query-forceOneShardAttributeValue"
36+
keyQueryTTL = "arangodb-query-ttl"
37+
keyQueryOptSatSyncWait = "arangodb-query-opt-satSyncWait"
38+
keyQueryOptFullCount = "arangodb-query-opt-fullCount"
39+
keyQueryOptStream = "arangodb-query-opt-stream"
40+
keyQueryOptProfile = "arangodb-query-opt-profile"
41+
keyQueryOptMaxRuntime = "arangodb-query-opt-maxRuntime"
4142
)
4243

4344
// WithQueryCount is used to configure a context that will set the Count of a query request,
@@ -70,6 +71,11 @@ func WithQueryMemoryLimit(parent context.Context, value int64) context.Context {
7071
return context.WithValue(contextOrBackground(parent), keyQueryMemoryLimit, value)
7172
}
7273

74+
// WithQueryForceOneShardAttributeValue is used to configure a context that will set the ForceOneShardAttributeValue of a query request,
75+
func WithQueryForceOneShardAttributeValue(parent context.Context, value string) context.Context {
76+
return context.WithValue(contextOrBackground(parent), keyQueryForceOneShardAttributeValue, value)
77+
}
78+
7379
// WithQueryTTL is used to configure a context that will set the TTL of a query request,
7480
func WithQueryTTL(parent context.Context, value time.Duration) context.Context {
7581
return context.WithValue(contextOrBackground(parent), keyQueryTTL, value)
@@ -179,6 +185,9 @@ type queryRequest struct {
179185
// MaxRuntime specify the timeout which can be used to kill a query on the server after the specified
180186
// amount in time. The timeout value is specified in seconds. A value of 0 means no timeout will be enforced.
181187
MaxRuntime float64 `json:"maxRuntime,omitempty"`
188+
// ForceOneShardAttributeValue This query option can be used in complex queries in case the query optimizer cannot
189+
// automatically detect that the query can be limited to only a single server (e.g. in a disjoint smart graph case).
190+
ForceOneShardAttributeValue *string `json:"forceOneShardAttributeValue,omitempty"`
182191
} `json:"options,omitempty"`
183192
}
184193

@@ -207,6 +216,11 @@ func (q *queryRequest) applyContextSettings(ctx context.Context) {
207216
q.MemoryLimit = value
208217
}
209218
}
219+
if rawValue := ctx.Value(keyQueryForceOneShardAttributeValue); rawValue != nil {
220+
if value, ok := rawValue.(string); ok {
221+
q.Options.ForceOneShardAttributeValue = &value
222+
}
223+
}
210224
if rawValue := ctx.Value(keyQueryTTL); rawValue != nil {
211225
if value, ok := rawValue.(time.Duration); ok {
212226
q.TTL = value.Seconds()

test/query_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,3 +229,41 @@ func TestProfileQuery(t *testing.T) {
229229
}
230230
})
231231
}
232+
233+
// TestForceOneShardAttributeValue test ForceOneShardAttributeValue query attribute.
234+
func TestForceOneShardAttributeValue(t *testing.T) {
235+
ctx, cancel := context.WithCancel(context.Background())
236+
defer cancel()
237+
238+
c := createClientFromEnv(t, true)
239+
240+
EnsureVersion(t, ctx, c).CheckVersion(MinimumVersion("3.9.0")).Cluster().Enterprise()
241+
242+
db := ensureDatabase(ctx, c, "force_one_shard_attribute_value", nil, t)
243+
244+
db, clean := prepareQueryDatabase(t, ctx, c, "force_one_shard_attribute_value")
245+
defer clean(t)
246+
247+
// Setup tests
248+
tests := []profileQueryTest{
249+
{
250+
Query: "FOR d IN books SORT d.Title RETURN d",
251+
},
252+
{
253+
Query: "FOR d IN books FILTER d.Title==@title SORT d.Title RETURN d",
254+
BindVars: map[string]interface{}{
255+
"title": "Book 16",
256+
},
257+
},
258+
}
259+
260+
t.Run("With ForceOneShardAttributeValue", func(t *testing.T) {
261+
for i, test := range tests {
262+
t.Run(fmt.Sprintf("Run %d", i), func(t *testing.T) {
263+
nCtx := driver.WithQueryForceOneShardAttributeValue(ctx, "value")
264+
_, err := db.Query(nCtx, test.Query, test.BindVars)
265+
require.NoError(t, err)
266+
})
267+
}
268+
})
269+
}

0 commit comments

Comments
 (0)