package db

import "upper.io/db.v3"

Package db (or upper-db) provides a common interface to work with different
data sources using adapters that wrap mature database drivers.

The main purpose of upper-db is to abstract common database operations and
encourage users perform advanced operations directly using the underlying
driver. upper-db supports the MySQL, PostgreSQL, SQLite and QL databases and
provides partial support (CRUD, no transactions) for MongoDB.

var (
ErrNoMoreRows = errors.New(`upper: no more rows in this result set`)
ErrNotConnected = errors.New(`upper: you're currently not connected`)
ErrMissingDatabaseName = errors.New(`upper: missing database name`)
ErrMissingCollectionName = errors.New(`upper: missing collection name`)
ErrCollectionDoesNotExist = errors.New(`upper: collection does not exist`)
ErrSockerOrHost = errors.New(`upper: you may connect either to a unix socket or a tcp address, but not both`)
ErrQueryLimitParam = errors.New(`upper: a query can accept only one limit parameter`)
ErrQuerySortParam = errors.New(`upper: a query can accept only one order by parameter`)
ErrQueryOffsetParam = errors.New(`upper: a query can accept only one offset parameter`)
ErrMissingConditions = errors.New(`upper: missing selector conditions`)
ErrUnsupported = errors.New(`upper: this action is currently unsupported on this database`)
ErrUndefined = errors.New(`upper: this value is undefined`)
ErrQueryIsPending = errors.New(`upper: can't execute this instruction while the result set is still open`)
ErrUnsupportedDestination = errors.New(`upper: unsupported destination type`)
ErrUnsupportedType = errors.New(`upper: this type does not support marshaling`)
ErrUnsupportedValue = errors.New(`upper: this value does not support unmarshaling`)
ErrUnknownConditionType = errors.New(`upper: arguments of type %T can't be used as constraints`)
ErrTooManyClients = errors.New(`upper: can't connect to database server: too many clients`)
ErrGivingUpTryingToConnect = errors.New(`upper: giving up trying to connect: too many clients`)
ErrMissingConnURL = errors.New(`upper: missing DSN`)
ErrNotImplemented = errors.New(`upper: call not implemented`)
ErrAlreadyWithinTransaction = errors.New(`upper: already within a transaction`)
)

type Collection interface {
// Insert inserts a new item into the collection, it accepts one argument
// that can be either a map or a struct. If the call suceeds, it returns the
// ID of the newly added element as an `interface{}` (the underlying type of
// this ID is unknown and depends on the database adapter). The ID returned
// by Insert() could be passed directly to Find() to retrieve the newly added
// element.Insert(interface{}) (interface{}, error)
// InsertReturning is like Insert() but it updates the passed pointer to map
// or struct with the newly inserted element (and with automatic fields, like
// IDs, timestamps, etc). This is all done atomically within a transaction.
// If the database does not support transactions this method returns
// db.ErrUnsupported.InsertReturning(interface{}) error// UpdateReturning takes a pointer to map or struct and tries to update the
// given item on the collection based on the item's primary keys. Once the
// element is updated, UpdateReturning will query the element that was just
// updated. If the database does not support transactions this method returns
// db.ErrUnsupportedUpdateReturning(interface{}) error// Exists returns true if the collection exists, false otherwise.Exists() bool// Find defines a new result set with elements from the collection.Find(...interface{}) Result// Truncate removes all elements on the collection and resets the
// collection's IDs.Truncate() error// Name returns the name of the collection.Name() string
}

Collection is an interface that defines methods useful for handling tables.

Compound represents an statement that has one or many sentences joined by by
an operator like "AND" or "OR". This is an exported interface but it's
rarely used directly, you may want to use the `db.And()` or `db.Or()`
functions instead.

Cond is a map that defines conditions for a query and satisfies the
Constraints and Compound interfaces.

Each entry of the map represents a condition (a column-value relation bound
by a comparison operator). The comparison operator is optional and can be
specified after the column name, if no comparison operator is provided the
equality is used.

Examples:

// Where age equals 18.
db.Cond{"age": 18}
// // Where age is greater than or equal to 18.
db.Cond{"age >=": 18}
// Where id is in a list of ids.
db.Cond{"id IN": []{1, 2, 3}}
// Where age is lower than 18 (you could use this syntax when using
// mongodb).
db.Cond{"age $lt": 18}
// Where age > 32 and age < 35
db.Cond{"age >": 32, "age <": 35}

type Constraint interface {
// Key is the leftmost part of the constraint and usually contains a column
// name.Key() interface{}
// Value if the rightmost part of the constraint and usually contains a
// column value.Value() interface{}
}

Constraint interface represents a single condition, like "a = 1". where `a`
is the key and `1` is the value. This is an exported interface but it's
rarely used directly, you may want to use the `db.Cond{}` map instead.

type Database interface {
// Driver returns the underlying driver the wrapper uses.
//
// In order to actually use the driver, the `interface{}` value needs to be
// casted into the appropriate type.
//
// Example:
// internalSQLDriver := sess.Driver().(*sql.DB)Driver() interface{}
// Open attempts to establish a connection with a DBMS.Open(ConnectionURL) error// Ping returns an error if the database manager could not be reached.Ping() error// Close closes the currently active connection to the database and clears
// caches.Close() error// Collection returns a collection reference given a table name.Collection(string) Collection// Collections returns the names of all non-system tables on the database.Collections() ([]string, error)
// Name returns the name of the active database.Name() string// ConnectionURL returns the data used to set up the adapter.ConnectionURL() ConnectionURL// ClearCache clears all the cache mechanisms the adapter is using.ClearCache()
Settings
}

Database is an interface that defines methods that must be satisfied by
all database adapters.

type RawValue interface {
fmt.StringerCompound// Raw returns the string representation of the value that the user wants to
// pass without any escaping.Raw() string// Arguments returns the arguments to be replaced on the query.Arguments() []interface{}
}

RawValue interface represents values that can bypass SQL filters. This is an
exported interface but it's rarely used directly, you may want to use
the `db.Raw()` function instead.

type Result interface {
// String satisfies fmt.Stringer and returns a SELECT statement for
// the result.String() string// Limit defines the maximum number of results in this set. It only has
// effect on `One()`, `All()` and `Next()`. A negative limit cancels any
// previous limit settings.Limit(int) Result// Offset ignores the first *n* results. It only has effect on `One()`,
// `All()` and `Next()`. A negative offset cancels any previous offset
// settings.Offset(int) Result// OrderBy receives field names that define the order in which elements will be
// returned in a query, field names may be prefixed with a minus sign (-)
// indicating descending order, ascending order will be used otherwise.OrderBy(...interface{}) Result// Select defines specific columns to be returned from the elements of the
// set.Select(...interface{}) Result// Where discards all the previously set filtering constraints (if any) and
// sets new ones. Commonly used when the conditions of the result depend on
// external parameters that are yet to be evaluated:
//
// res := col.Find()
//
// if ... {
// res.Where(...)
// } else {
// res.Where(...)
// }Where(...interface{}) Result// And adds more filtering conditions on top of the existing constraints.
//
// res := col.Find(...).And(...)And(...interface{}) Result// Group is used to group results that have the same value in the same column
// or columns.Group(...interface{}) Result// Delete deletes all items within the result set. `Offset()` and `Limit()` are
// not honoured by `Delete()`.Delete() error// Update modifies all items within the result set. `Offset()` and `Limit()`
// are not honoured by `Update()`.Update(interface{}) error// Count returns the number of items that match the set conditions. `Offset()`
// and `Limit()` are not honoured by `Count()`Count() (uint64, error)
// Exists returns true if at least one item on the collection exists. False
// otherwise.Exists() (bool, error)
// Next fetches the next result within the result set and dumps it into the
// given pointer to struct or pointer to map. You must call
// `Close()` after finishing using `Next()`.Next(ptrToStruct interface{}) bool// Err returns the last error that has happened with the result set, nil
// otherwise.Err() error// One fetches the first result within the result set and dumps it into the
// given pointer to struct or pointer to map. The result set is automatically
// closed after picking the element, so there is no need to call Close()
// after using One().One(ptrToStruct interface{}) error// All fetches all results within the result set and dumps them into the
// given pointer to slice of maps or structs. The result set is
// automatically closed, so there is no need to call Close() after
// using All().All(sliceOfStructs interface{}) error// Paginate splits the results of the query into pages containing pageSize
// items. When using pagination previous settings for Limit and Offset are
// ignored. Page numbering starts at 1.
//
// Use Page() to define the specific page to get results from.
//
// Example:
//
// r = q.Paginate(12)
//
// You can provide constraints an order settings when using pagination:
//
// Example:
//
// res := q.Where(conds).OrderBy("-id").Paginate(12)
// err := res.Page(4).All(&items)Paginate(pageSize uint) Result// Page makes the result set return results only from the page identified by
// pageNumber. Page numbering starts from 0.
//
// Example:
//
// r = q.Paginate(12).Page(4)Page(pageNumber uint) Result// Cursor defines the column that is going to be taken as basis for
// cursor-based pagination.
//
// Example:
//
// a = q.Paginate(10).Cursor("id")
// b = q.Paginate(12).Cursor("-id")
//
// You can set "" as cursorColumn to disable cursors.Cursor(cursorColumn string) Result// NextPage returns the next results page according to the cursor. It expects
// a cursorValue, which is the value the cursor column had on the last item
// of the current result set (lower bound).
//
// Example:
//
// cursor = q.Paginate(12).Cursor("id")
// res = cursor.NextPage(items[len(items)-1].ID)
//
// Note that NextPage requires a cursor, any column with an absolute order
// (given two values one always precedes the other) can be a cursor.
//
// You can define the pagination order and add constraints to your result:
//
// cursor = q.Where(...).OrderBy("id").Paginate(10).Cursor("id")
// res = cursor.NextPage(lowerBound)NextPage(cursorValue interface{}) Result// PrevPage returns the previous results page according to the cursor. It
// expects a cursorValue, which is the value the cursor column had on the
// fist item of the current result set (upper bound).
//
// Example:
//
// current = current.PrevPage(items[0].ID)
//
// Note that PrevPage requires a cursor, any column with an absolute order
// (given two values one always precedes the other) can be a cursor.
//
// You can define the pagination order and add constraints to your result:
//
// cursor = q.Where(...).OrderBy("id").Paginate(10).Cursor("id")
// res = cursor.PrevPage(upperBound)PrevPage(cursorValue interface{}) Result// TotalPages returns the total number of pages the result could produce. If
// no pagination has been set this value equals 1.TotalPages() (uint, error)
// TotalEntries returns the total number of entries in the query.TotalEntries() (uint64, error)
// Close closes the result set and frees all locked resources.Close() error
}

Result is an interface that defines methods useful for working with result
sets.