entites.md 3.5 KB

Model entities implement the EntityInterface, which combines:

  • the StorableEntityInterface, which allows them to call upon

    • a storage controller, implementing the StorageControllerInterface

    StorableEntityInterface

    StorageController() StorageControllerInterface
    

The storage controllers implement the StorageControllerInterface, which defines:

  • the collection holding the data
  • the data id: the name of the possibly multiple data keys to combine to identify an entity
  • the driver to use to access the data

    StorageControllerInterface

    Collection() string
    Id() []string
    Driver() *StorageDriverInterface
    

The storage drivers implement the StorageDriver interface, which defines:

  • the underlying opaque go-level object
  • database enumeration

The storage driver instances are likely to be shared objects, hence may not contain any per-controller or per-entity information, and cannot be embedded in storage controllers, but must be standalone

StorageDriverInterface
    DbDriver() interface{}
    Databases() []DatabaseInterface
    DropDatabase(db DatabaseInterface)      
    MakeDatabase() DatabaseInterface

Storage drivers may exist in multiple instances, to address multiple connections to different DB servers. Multiple driver instance MUST NOT address the same server, to avoid consistency issues.

Databases implement the DatabaseInterface, which defines:

  • collection enumeration
  • collection access by name
  • collection deletion

    DatabaseInterface

    Collections() []string
    Collection(name) CollectionInterface
    DropCollection(name string)
    

Collections implement the Collection interface, which defines:

  • document (row) CRUD
  • truncation

    CollectionInterface

    Truncate()
    Document(id IdInterface)
    Find(crit CriteriumInterface) QueryInterface
    

Criteria implement the CriteriumInterface

CriteriumInterface
    Fields() []string

Queries are promises implementing the QueryInterface. They are meant to be used as a fluent interface, like: cursor, err := coll.Find(someCriteria).Order(someOrdering).Execute()

QueryInterface
    Execute() ExecutedQueryInterface
    Order([]OrderSpecification) QueryInterface
    Skip(offset int64) QueryInterface
    Limit(count int64) QueryInterface
    Count() int64
    Fields() []string

Note that Fields() will only return the fields specifically requested. If the query does not specify fields (like SQL "SELECT *" or MongoDB "coll.find({})", it will return empty.

Executed queries implement the ExecutedQueryInterface. They provide access to the non-executed query, a cursor, and the fields available in all documents (which) may need cursor unrolling and be very costly)

ExecutedQueryInterface
    Cursor() CursorInterface
    Query() QueryInterface
    Fields() []string

For selection queries returning multiple documents, the cursor will typically be iterated. Selection queries returning a single document are just a case of 1 being a value of n. Count queries and modification queries return a cursor to available data, like count, affected documents or last insert id. The available columns depend on the query type, hence the use of Fields().

Every database driver provides support for queries which this set of interfaces cannot build. Applications needing to build such queries, can use DbDriver() to access the database driver for their custom needs, losing database-independence.

They can limit the db-dependent part by building an ExecutedQueryInterface from their results, at which point code can resume db independence. Bridge packages can provide this mapping.