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	Cluster        *ClusterStats   `json:"cluster,omitempty"`
107	RawResponse    json.RawMessage `json:"-"`
108}
109
110// ClusterStats contains the cluster configuration for the database.
111type ClusterStats struct {
112	Replicas    int `json:"n"`
113	Shards      int `json:"q"`
114	ReadQuorum  int `json:"r"`
115	WriteQuorum int `json:"w"`
116}
117
118// Members represents the members of a database security document.
119type Members struct {
120	Names []string `json:"names,omitempty"`
121	Roles []string `json:"roles,omitempty"`
122}
123
124// Security represents a database security document.
125type Security struct {
126	Admins  Members `json:"admins"`
127	Members Members `json:"members"`
128}
129
130// DB is a database handle.
131type DB interface {
132	// AllDocs returns all of the documents in the database, subject to the
133	// options provided.
134	AllDocs(ctx context.Context, options map[string]interface{}) (Rows, error)
135	// Get fetches the requested document from the database, and unmarshals it
136	// into doc.
137	Get(ctx context.Context, docID string, options map[string]interface{}) (json.RawMessage, error)
138	// CreateDoc creates a new doc, with a server-generated ID.
139	CreateDoc(ctx context.Context, doc interface{}) (docID, rev string, err error)
140	// Put writes the document in the database.
141	Put(ctx context.Context, docID string, doc interface{}) (rev string, err error)
142	// Delete marks the specified document as deleted.
143	Delete(ctx context.Context, docID, rev string) (newRev string, err error)
144	// Stats returns database statistics.
145	Stats(ctx context.Context) (*DBStats, error)
146	// Compact initiates compaction of the database.
147	Compact(ctx context.Context) error
148	// CompactView initiates compaction of the view.
149	CompactView(ctx context.Context, ddocID string) error
150	// ViewCleanup cleans up stale view files.
151	ViewCleanup(ctx context.Context) error
152	// Security returns the database's security document.
153	Security(ctx context.Context) (*Security, error)
154	// SetSecurity sets the database's security document.
155	SetSecurity(ctx context.Context, security *Security) error
156	// Changes returns a Rows iterator for the changes feed. In continuous mode,
157	// the iterator will continue indefinitely, until Close is called.
158	Changes(ctx context.Context, options map[string]interface{}) (Changes, error)
159	// PutAttachment uploads an attachment to the specified document, returning
160	// the new revision.
161	PutAttachment(ctx context.Context, docID, rev, filename, contentType string, body io.Reader) (newRev string, err error)
162	// GetAttachment fetches an attachment for the associated document ID. rev
163	// may be an empty string to fetch the most recent document version.
164	GetAttachment(ctx context.Context, docID, rev, filename string) (contentType string, md5sum MD5sum, body io.ReadCloser, err error)
165	// DeleteAttachment deletes an attachment from a document, returning the
166	// document's new revision.
167	DeleteAttachment(ctx context.Context, docID, rev, filename string) (newRev string, err error)
168	// Query performs a query against a view, subject to the options provided.
169	// ddoc will be the design doc name without the '_design/' previx.
170	// view will be the view name without the '_view/' prefix.
171	Query(ctx context.Context, ddoc, view string, options map[string]interface{}) (Rows, error)
172}
173
174// DBOpts will be merged with DB in Kivik 2.0. It wraps functions that take
175// additional options arguments.
176type DBOpts interface {
177	CreateDocOpts(ctx context.Context, doc interface{}, options map[string]interface{}) (docID, rev string, err error)
178	// PutOpts writes the document in the database.
179	PutOpts(ctx context.Context, docID string, doc interface{}, options map[string]interface{}) (rev string, err error)
180	// DeleteOpts marks the specified document as deleted.
181	DeleteOpts(ctx context.Context, docID, rev string, options map[string]interface{}) (newRev string, err error)
182	// StatsOpts returns database statistics.
183	PutAttachmentOpts(ctx context.Context, docID, rev, filename, contentType string, body io.Reader, options map[string]interface{}) (newRev string, err error)
184	// GetAttachmentOpts fetches an attachment for the associated document ID. rev
185	// may be an empty string to fetch the most recent document version.
186	GetAttachmentOpts(ctx context.Context, docID, rev, filename string, options map[string]interface{}) (contentType string, md5sum MD5sum, body io.ReadCloser, err error)
187	// DeleteAttachmentOpts deletes an attachment from a document, returning the
188	// document's new revision.
189	DeleteAttachmentOpts(ctx context.Context, docID, rev, filename string, options map[string]interface{}) (newRev string, err error)
190}
191
192// OldBulkDocer is deprecated and will be removed in Kivik 2.0. Use BulkDocer instead.
193type OldBulkDocer interface {
194	// BulkDocs alls bulk create, update and/or delete operations. It returns an
195	// iterator over the results.
196	BulkDocs(ctx context.Context, docs []interface{}) (BulkResults, error)
197}
198
199// BulkDocer is an optional interface which may be implemented by a driver to
200// support bulk insert/update operations. For any driver that does not support
201// the BulkDocer interface, the Put or CreateDoc methods will be called for each
202// document to emulate the same functionality.
203type BulkDocer interface {
204	// BulkDocs alls bulk create, update and/or delete operations. It returns an
205	// iterator over the results.
206	BulkDocs(ctx context.Context, docs []interface{}, options map[string]interface{}) (BulkResults, error)
207}
208
209// The Finder is an optional interface which may be implemented by a database. The
210// Finder interface provides access to the new (in CouchDB 2.0) MongoDB-style
211// query interface.
212type Finder interface {
213	// Find executes a query using the new /_find interface. If query is a
214	// string, []byte, or json.RawMessage, it should be treated as a raw JSON
215	// payload. Any other type should be marshaled to JSON.
216	Find(ctx context.Context, query interface{}) (Rows, error)
217	// CreateIndex creates an index if it doesn't already exist. If the index
218	// already exists, it should do nothing. ddoc and name may be empty, in
219	// which case they should be provided by the backend. If index is a string,
220	// []byte, or json.RawMessage, it should be treated as a raw JSON payload.
221	// Any other type should be marshaled to JSON.
222	CreateIndex(ctx context.Context, ddoc, name string, index interface{}) error
223	// GetIndexes returns a list of all indexes in the database.
224	GetIndexes(ctx context.Context) ([]Index, error)
225	// Delete deletes the requested index.
226	DeleteIndex(ctx context.Context, ddoc, name string) 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// The Explainer is an optional interface which provides access to the query
245// explanation API supported by CouchDB 2.0 and newer, and PouchDB 6.3.4 and
246// newer.
247type Explainer interface {
248	Explain(ctx context.Context, query interface{}) (*QueryPlan, error)
249}
250
251// Index is a MonboDB-style index definition.
252type Index struct {
253	DesignDoc  string      `json:"ddoc,omitempty"`
254	Name       string      `json:"name"`
255	Type       string      `json:"type"`
256	Definition interface{} `json:"def"`
257}
258
259// MD5sum is a 128-bit MD5 checksum.
260type MD5sum [16]byte
261
262// OldAttachmentMetaer is deprected. Use AttachmentMetaer instead.
263type OldAttachmentMetaer interface {
264	// GetAttachmentMeta returns meta information about an attachment.
265	GetAttachmentMeta(ctx context.Context, docID, rev, filename string) (contentType string, md5sum MD5sum, err error)
266}
267
268// AttachmentMetaer is an optional interface which may be satisfied by a
269// DB. If satisfied, it may be used to fetch meta data about an attachment. If
270// not satisfied, GetAttachment will be used instead.
271type AttachmentMetaer interface {
272	// GetAttachmentMetaOpts returns meta information about an attachment.
273	GetAttachmentMeta(ctx context.Context, docID, rev, filename string, options map[string]interface{}) (contentType string, md5sum MD5sum, err error)
274}
275
276// BulkResult is the result of a single doc update in a BulkDocs request.
277type BulkResult struct {
278	ID    string `json:"id"`
279	Rev   string `json:"rev"`
280	Error error
281}
282
283// BulkResults is an iterator over the results for a BulkDocs call.
284type BulkResults interface {
285	// Next is called to populate *BulkResult with the values of the next bulk
286	// result in the set.
287	//
288	// Next should return io.EOF when there are no more results.
289	Next(*BulkResult) error
290	// Close closes the bulk results iterator.
291	Close() error
292}
293
294// Rever is an optional interface that may be implemented by a database. If not
295// implemented by the driver, the Get method will be used to emulate the
296// functionality.
297type Rever interface {
298	// Rev returns the most current revision of the requested document.
299	Rev(ctx context.Context, docID string) (rev string, err error)
300}
301
302// DBFlusher is an optional interface that may be implemented by a database
303// that can force a flush of the database backend file(s) to disk or other
304// permanent storage.
305type DBFlusher interface {
306	// Flush requests a flush of disk cache to disk or other permanent storage.
307	//
308	// See http://docs.couchdb.org/en/2.0.0/api/database/compact.html#db-ensure-full-commit
309	Flush(ctx context.Context) error
310}
311
312// Copier is an optional interface that may be implemented by a DB.
313//
314// If a DB does implement Copier, Copy() functions will use it.  If a DB does
315// not implement the Copier interface, or if a call to Copy() returns an
316// http.StatusUnimplemented, the driver will emulate a copy by doing
317// a GET followed by PUT.
318type Copier interface {
319	Copy(ctx context.Context, targetID, sourceID string, options map[string]interface{}) (targetRev string, err error)
320}
321