1package driver
2
3import (
4	"context"
5	"encoding/json"
6	"io"
7	"time"
8)
9
10// Driver is the interface that must be implemented by a database driver.
11type Driver interface {
12	// NewClient returns a connection handle to the database. The name is in a
13	// driver-specific format.
14	NewClient(ctx context.Context, name string) (Client, error)
15}
16
17// Version represents a server version response.
18type Version struct {
19	// Version is the version number reported by the server or backend.
20	Version string
21	// Vendor is the vendor string reported by the server or backend.
22	Vendor string
23	// Features is a list of enabled, optional features.  This was added in
24	// CouchDB 2.1.0, and can be expected to be empty for older versions.
25	Features []string
26	// RawResponse is the raw response body as returned by the server.
27	RawResponse json.RawMessage
28}
29
30// Client is a connection to a database server.
31type Client interface {
32	// Version returns the server implementation's details.
33	Version(ctx context.Context) (*Version, error)
34	// AllDBs returns a list of all existing database names.
35	AllDBs(ctx context.Context, options map[string]interface{}) ([]string, error)
36	// DBExists returns true if the database exists.
37	DBExists(ctx context.Context, dbName string, options map[string]interface{}) (bool, error)
38	// CreateDB creates the requested DB. The dbName is validated as a valid
39	// CouchDB database name prior to calling this function, so the driver can
40	// assume a valid name.
41	CreateDB(ctx context.Context, dbName string, options map[string]interface{}) error
42	// DestroyDB deletes the requested DB.
43	DestroyDB(ctx context.Context, dbName string, options map[string]interface{}) error
44	// DB returns a handleto the requested database
45	DB(ctx context.Context, dbName string, options map[string]interface{}) (DB, error)
46}
47
48// Replication represents a _replicator document.
49type Replication interface {
50	// The following methods are called just once, when the Replication is first
51	// returned from Replicate() or GetReplications().
52	ReplicationID() string
53	Source() string
54	Target() string
55	StartTime() time.Time
56	EndTime() time.Time
57	State() string
58	Err() error
59
60	// These methods may be triggered by user actions.
61
62	// Delete deletes a replication, which cancels it if it is running.
63	Delete(context.Context) error
64	// Update fetches the latest replication state from the server.
65	Update(context.Context, *ReplicationInfo) error
66}
67
68// ReplicationInfo represents a snap-shot state of a replication, as provided
69// by the _active_tasks endpoint.
70type ReplicationInfo struct {
71	DocWriteFailures int64
72	DocsRead         int64
73	DocsWritten      int64
74	Progress         float64
75}
76
77// ClientReplicator is an optional interface that may be implemented by a Client
78// that supports replication between two database.
79type ClientReplicator interface {
80	// Replicate initiates a replication.
81	Replicate(ctx context.Context, targetDSN, sourceDSN string, options map[string]interface{}) (Replication, error)
82	// GetReplications returns a list of replicatoins (i.e. all docs in the
83	// _replicator database)
84	GetReplications(ctx context.Context, options map[string]interface{}) ([]Replication, error)
85}
86
87// Authenticator is an optional interface that may be implemented by a Client
88// that supports authenitcated connections.
89type Authenticator interface {
90	// Authenticate attempts to authenticate the client using an authenticator.
91	// If the authenticator is not known to the client, an error should be
92	// returned.
93	Authenticate(ctx context.Context, authenticator interface{}) error
94}
95
96// DBStats contains database statistics..
97type DBStats struct {
98	Name           string `json:"db_name"`
99	CompactRunning bool   `json:"compact_running"`
100	DocCount       int64  `json:"doc_count"`
101	DeletedCount   int64  `json:"doc_del_count"`
102	UpdateSeq      string `json:"update_seq"`
103	DiskSize       int64  `json:"disk_size"`
104	ActiveSize     int64  `json:"data_size"`
105	ExternalSize   int64  `json:"-"`
106}
107
108// Members represents the members of a database security document.
109type Members struct {
110	Names []string `json:"names,omitempty"`
111	Roles []string `json:"roles,omitempty"`
112}
113
114// Security represents a database security document.
115type Security struct {
116	Admins  Members `json:"admins"`
117	Members Members `json:"members"`
118}
119
120// DB is a database handle.
121type DB interface {
122	// AllDocs returns all of the documents in the database, subject to the
123	// options provided.
124	AllDocs(ctx context.Context, options map[string]interface{}) (Rows, error)
125	// Get fetches the requested document from the database, and returns the
126	// content length (or -1 if unknown), and an io.ReadCloser to access the
127	// raw JSON content.
128	Get(ctx context.Context, docID string, options map[string]interface{}) (*Document, error)
129	// CreateDoc creates a new doc, with a server-generated ID.
130	CreateDoc(ctx context.Context, doc interface{}, options map[string]interface{}) (docID, rev string, err error)
131	// Put writes the document in the database.
132	Put(ctx context.Context, docID string, doc interface{}, options map[string]interface{}) (rev string, err error)
133	// Delete marks the specified document as deleted.
134	Delete(ctx context.Context, docID, rev string, options map[string]interface{}) (newRev string, err error)
135	// Stats returns database statistics.
136	Stats(ctx context.Context) (*DBStats, error)
137	// Compact initiates compaction of the database.
138	Compact(ctx context.Context) error
139	// CompactView initiates compaction of the view.
140	CompactView(ctx context.Context, ddocID string) error
141	// ViewCleanup cleans up stale view files.
142	ViewCleanup(ctx context.Context) error
143	// Security returns the database's security document.
144	Security(ctx context.Context) (*Security, error)
145	// SetSecurity sets the database's security document.
146	SetSecurity(ctx context.Context, security *Security) error
147	// Changes returns a Rows iterator for the changes feed. In continuous mode,
148	// the iterator will continue indefinitely, until Close is called.
149	Changes(ctx context.Context, options map[string]interface{}) (Changes, error)
150	// PutAttachment uploads an attachment to the specified document, returning
151	// the new revision.
152	PutAttachment(ctx context.Context, docID, rev string, att *Attachment, options map[string]interface{}) (newRev string, err error)
153	// GetAttachment fetches an attachment for the associated document ID. rev
154	// may be an empty string to fetch the most recent document version.
155	GetAttachment(ctx context.Context, docID, rev, filename string, options map[string]interface{}) (*Attachment, error)
156	// DeleteAttachment deletes an attachment from a document, returning the
157	// document's new revision.
158	DeleteAttachment(ctx context.Context, docID, rev, filename string, options map[string]interface{}) (newRev string, err error)
159	// Query performs a query against a view, subject to the options provided.
160	// ddoc will be the design doc name without the '_design/' previx.
161	// view will be the view name without the '_view/' prefix.
162	Query(ctx context.Context, ddoc, view string, options map[string]interface{}) (Rows, error)
163}
164
165// Document represents a single document returned by Get
166type Document struct {
167	// ContentLength is the size of the document response in bytes.
168	ContentLength int64
169
170	// Rev is the revision number returned
171	Rev string
172
173	// Body contains the respons body, either in raw JSON or multipart/related
174	// format.
175	Body io.ReadCloser
176
177	// Attachments will be nil except when include_docs=true.
178	Attachments Attachments
179}
180
181// Attachments is an iterator over the attachments included in a document when
182// Get is called with `include_docs=true`.
183type Attachments interface {
184	// Next is called to pupulate att with the next attachment in the result
185	// set.
186	//
187	//
188	// Next should return io.EOF when there are no more attachments.
189	Next(att *Attachment) error
190
191	// Close closes the Attachments iterator
192	Close() error
193}
194
195// BulkDocer is an optional interface which may be implemented by a DB to
196// support bulk insert/update operations. For any driver that does not support
197// the BulkDocer interface, the Put or CreateDoc methods will be called for each
198// document to emulate the same functionality, with options passed through
199// unaltered.
200type BulkDocer interface {
201	// BulkDocs alls bulk create, update and/or delete operations. It returns an
202	// iterator over the results.
203	BulkDocs(ctx context.Context, docs []interface{}, options map[string]interface{}) (BulkResults, error)
204}
205
206// Finder is an optional interface which may be implemented by a DB. The Finder
207// interface provides access to the new (in CouchDB 2.0) MongoDB-style query
208// interface.
209type Finder interface {
210	// Find executes a query using the new /_find interface. If query is a
211	// string, []byte, or json.RawMessage, it should be treated as a raw JSON
212	// payload. Any other type should be marshaled to JSON.
213	Find(ctx context.Context, query interface{}) (Rows, error)
214	// CreateIndex creates an index if it doesn't already exist. If the index
215	// already exists, it should do nothing. ddoc and name may be empty, in
216	// which case they should be provided by the backend. If index is a string,
217	// []byte, or json.RawMessage, it should be treated as a raw JSON payload.
218	// Any other type should be marshaled to JSON.
219	CreateIndex(ctx context.Context, ddoc, name string, index interface{}) error
220	// GetIndexes returns a list of all indexes in the database.
221	GetIndexes(ctx context.Context) ([]Index, error)
222	// Delete deletes the requested index.
223	DeleteIndex(ctx context.Context, ddoc, name string) error
224	// Explain returns the query plan for a given query. Explain takes the same
225	// arguments as Find.
226	Explain(ctx context.Context, query interface{}) (*QueryPlan, error)
227}
228
229// QueryPlan is the response of an Explain query.
230type QueryPlan struct {
231	DBName   string                 `json:"dbname"`
232	Index    map[string]interface{} `json:"index"`
233	Selector map[string]interface{} `json:"selector"`
234	Options  map[string]interface{} `json:"opts"`
235	Limit    int64                  `json:"limit"`
236	Skip     int64                  `json:"skip"`
237
238	// Fields is the list of fields to be returned in the result set, or
239	// an empty list if all fields are to be returned.
240	Fields []interface{}          `json:"fields"`
241	Range  map[string]interface{} `json:"range"`
242}
243
244// Index is a MonboDB-style index definition.
245type Index struct {
246	DesignDoc  string      `json:"ddoc,omitempty"`
247	Name       string      `json:"name"`
248	Type       string      `json:"type"`
249	Definition interface{} `json:"def"`
250}
251
252// Attachment represents a file attachment to a document.
253type Attachment struct {
254	Filename        string        `json:"-"`
255	ContentType     string        `json:"content_type"`
256	Stub            bool          `json:"stub"`
257	Content         io.ReadCloser `json:"-"`
258	Size            int64         `json:"length"`
259	ContentEncoding string        `json:"encoding"`
260	EncodedLength   int64         `json:"encoded_length"`
261	RevPos          int64         `json:"revpos"`
262	Digest          string        `json:"digest"`
263}
264
265// AttachmentMetaGetter is an optional interface which may be satisfied by a
266// DB. If satisfied, it may be used to fetch meta data about an attachment. If
267// not satisfied, GetAttachment will be used instead.
268type AttachmentMetaGetter interface {
269	// GetAttachmentMetaOpts returns meta information about an attachment.
270	GetAttachmentMeta(ctx context.Context, docID, rev, filename string, options map[string]interface{}) (*Attachment, error)
271}
272
273// BulkResult is the result of a single doc update in a BulkDocs request.
274type BulkResult struct {
275	ID    string `json:"id"`
276	Rev   string `json:"rev"`
277	Error error
278}
279
280// BulkResults is an iterator over the results for a BulkDocs call.
281type BulkResults interface {
282	// Next is called to populate *BulkResult with the values of the next bulk
283	// result in the set.
284	//
285	// Next should return io.EOF when there are no more results.
286	Next(*BulkResult) error
287	// Close closes the bulk results iterator.
288	Close() error
289}
290
291// MetaGetter is an optional interface that may be implemented by a DB. If not
292// implemented, the Get method will be used to emulate the functionality, with
293// options passed through unaltered.
294type MetaGetter interface {
295	// GetMeta returns the document size and revision of the requested document.
296	// GetMeta should accept the same options as the Get method.
297	GetMeta(ctx context.Context, docID string, options map[string]interface{}) (size int64, rev string, err error)
298}
299
300// Flusher is an optional interface that may be implemented by a DB that can
301// force a flush of the database backend file(s) to disk or other permanent
302// storage.
303type Flusher interface {
304	// Flush requests a flush of disk cache to disk or other permanent storage.
305	//
306	// See http://docs.couchdb.org/en/2.0.0/api/database/compact.html#db-ensure-full-commit
307	Flush(ctx context.Context) error
308}
309
310// Copier is an optional interface that may be implemented by a DB.
311//
312// If a DB does implement Copier, Copy() functions will use it. If a DB does
313// not implement the Copier interface, the functionality will be emulated by
314// calling Get followed by Put, with options passed through unaltered, except
315// that the 'rev' option will be removed for the Put call.
316type Copier interface {
317	Copy(ctx context.Context, targetID, sourceID string, options map[string]interface{}) (targetRev string, err error)
318}
319