blob: ad6b9f5f5b8c1ba6de7dbd169cd47b9bab214828 [file] [log] [blame]
// 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 nosql defines the wire API for the NoSQL part of Syncbase.
package nosql
import (
"v.io/v23/security/access"
"v.io/v23/services/permissions"
)
// Database represents a collection of Tables. Batches, queries, sync, watch,
// etc. all operate at the Database level.
// Database.Glob operates over Table names.
//
// TODO(sadovsky): Add Watch method.
type Database interface {
// Create creates this Database.
// If perms is nil, we inherit (copy) the App perms.
// Create requires the caller to have Write permission at the App.
Create(perms access.Permissions) error {access.Write}
// Delete deletes this Database.
Delete() error {access.Write}
// BeginBatch creates a new batch. It returns an App-relative name for a
// Database handle bound to this batch. If this Database is already bound to a
// batch, BeginBatch() will fail with ErrBoundToBatch. Concurrency semantics
// are documented in model.go.
BeginBatch(bo BatchOptions) (string | error) {access.Read}
// Commit persists the pending changes to the database.
// If this Database is not bound to a batch, Commit() will fail with
// ErrNotBoundToBatch.
Commit() error {access.Read}
// Exec executes a syncQL query and returns all results as specified by in the
// query's select clause. Concurrency semantics are documented in model.go.
Exec(query string) stream<_, []any> error {access.Read}
// Abort notifies the server that any pending changes can be discarded.
// It is not strictly required, but it may allow the server to release locks
// or other resources sooner than if it was not called.
// If this Database is not bound to a batch, Abort() will fail with
// ErrNotBoundToBatch.
Abort() error {access.Read}
// SetPermissions and GetPermissions are included from the Object interface.
permissions.Object
// SyncGroupManager implements the API for managing SyncGroups attached to a
// Database.
SyncGroupManager
}
// Table represents a collection of Rows.
// Table.Glob operates over the primary keys of Rows in the Table.
type Table interface {
// Create creates this Table.
// If perms is nil, we inherit (copy) the Database perms.
Create(perms access.Permissions) error {access.Write}
// Delete deletes this Table.
Delete() error {access.Write}
// Delete deletes all rows in the given half-open range [start, limit). If
// limit is "", all rows with keys >= start are included.
DeleteRowRange(start, limit []byte) error {access.Write}
// Scan returns all rows in the given half-open range [start, limit). If limit
// is "", all rows with keys >= start are included. Concurrency semantics are
// documented in model.go.
Scan(start, limit []byte) stream<_, KeyValue> error {access.Read}
// GetPermissions returns an array of (prefix, perms) pairs. The array is
// sorted from longest prefix to shortest, so element zero is the one that
// applies to the row with the given key. The last element is always the
// prefix "" which represents the table's permissions -- the array will always
// have at least one element.
GetPermissions(key string) ([]PrefixPermissions | error) {access.Admin}
// SetPermissions sets the permissions for all current and future rows with
// the given prefix. If the prefix overlaps with an existing prefix, the
// longest prefix that matches a row applies. For example:
// SetPermissions(ctx, Prefix("a/b"), perms1)
// SetPermissions(ctx, Prefix("a/b/c"), perms2)
// The permissions for row "a/b/1" are perms1, and the permissions for row
// "a/b/c/1" are perms2.
SetPermissions(prefix string, perms access.Permissions) error {access.Admin}
// DeletePermissions deletes the permissions for the specified prefix. Any
// rows covered by this prefix will use the next longest prefix's permissions
// (see the array returned by GetPermissions).
DeletePermissions(prefix string) error {access.Admin}
}
// Row represents a single row in a Table.
// All access checks are performed against the most specific matching prefix
// permissions in the Table.
// NOTE(sadovsky): Currently we send []byte values over the wire for Get, Put,
// and Scan. If there's a way to avoid encoding/decoding on the server side, we
// can use vdl.Value everywhere without sacrificing performance.
type Row interface {
// Get returns the value for this Row.
Get() ([]byte | error) {access.Read}
// Put writes the given value for this Row.
Put(value []byte) error {access.Write}
// Delete deletes this Row.
Delete() error {access.Write}
}
// SyncGroupManager is the interface for SyncGroup operations.
// TODO(hpucha): Add blessings to create/join and add a refresh method.
type SyncGroupManager interface {
// GetSyncGroupNames returns the global names of all SyncGroups attached to
// this database.
GetSyncGroupNames() ([]string | error) {access.Read}
// CreateSyncGroup creates a new SyncGroup with the given spec.
//
// Requires: Client must have at least Read access on the Database; prefix ACL
// must exist at each SyncGroup prefix; Client must have at least Read access
// on each of these prefix ACLs.
CreateSyncGroup(sgName string, spec SyncGroupSpec, myInfo SyncGroupMemberInfo) error {access.Read}
// JoinSyncGroup joins the SyncGroup.
//
// Requires: Client must have at least Read access on the Database and on the
// SyncGroup ACL.
JoinSyncGroup(sgName string, myInfo SyncGroupMemberInfo) (spec SyncGroupSpec | error) {access.Read}
// LeaveSyncGroup leaves the SyncGroup. Previously synced data will continue
// to be available.
//
// Requires: Client must have at least Read access on the Database.
LeaveSyncGroup(sgName string) error {access.Read}
// DestroySyncGroup destroys the SyncGroup. Previously synced data will
// continue to be available to all members.
//
// Requires: Client must have at least Read access on the Database, and must
// have Admin access on the SyncGroup ACL.
DestroySyncGroup(sgName string) error {access.Read}
// EjectFromSyncGroup ejects a member from the SyncGroup. The ejected member
// will not be able to sync further, but will retain any data it has already
// synced.
//
// Requires: Client must have at least Read access on the Database, and must
// have Admin access on the SyncGroup ACL.
EjectFromSyncGroup(sgName, member string) error {access.Read}
// GetSyncGroupSpec gets the SyncGroup spec. version allows for atomic
// read-modify-write of the spec - see comment for SetSyncGroupSpec.
//
// Requires: Client must have at least Read access on the Database and on the
// SyncGroup ACL.
GetSyncGroupSpec(sgName string) (spec SyncGroupSpec, version string | error) {access.Read}
// SetSyncGroupSpec sets the SyncGroup spec. version may be either empty or
// the value from a previous Get. If not empty, Set will only succeed if the
// current version matches the specified one.
//
// Requires: Client must have at least Read access on the Database, and must
// have Admin access on the SyncGroup ACL.
SetSyncGroupSpec(sgName string, spec SyncGroupSpec, version string) error {access.Read}
// GetSyncGroupMembers gets the info objects for members of the SyncGroup.
//
// Requires: Client must have at least Read access on the Database and on the
// SyncGroup ACL.
GetSyncGroupMembers(sgName string) (members map[string]SyncGroupMemberInfo | error) {access.Read}
// TODO(hpucha): Add support for client-side conflict resolution and sync
// policies.
// StartConflictResolution(name string) stream<ResolutionInfo, ConflictInfo> error
// Suspend/ResumeSync
// Get/SetSyncPolicy with policies such as "sync only via wifi", "sync
// aggressively", "sync once per day".
}
error (
BoundToBatch() {"en": "bound to batch"}
NotBoundToBatch() {"en": "not bound to batch"}
ReadOnlyBatch() {"en": "batch is read-only"}
)