123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- package memdb
- import "fmt"
- // DBSchema is the schema to use for the full database with a MemDB instance.
- //
- // MemDB will require a valid schema. Schema validation can be tested using
- // the Validate function. Calling this function is recommended in unit tests.
- type DBSchema struct {
- // Tables is the set of tables within this database. The key is the
- // table name and must match the Name in TableSchema.
- Tables map[string]*TableSchema
- }
- // Validate validates the schema.
- func (s *DBSchema) Validate() error {
- if s == nil {
- return fmt.Errorf("schema is nil")
- }
- if len(s.Tables) == 0 {
- return fmt.Errorf("schema has no tables defined")
- }
- for name, table := range s.Tables {
- if name != table.Name {
- return fmt.Errorf("table name mis-match for '%s'", name)
- }
- if err := table.Validate(); err != nil {
- return fmt.Errorf("table %q: %s", name, err)
- }
- }
- return nil
- }
- // TableSchema is the schema for a single table.
- type TableSchema struct {
- // Name of the table. This must match the key in the Tables map in DBSchema.
- Name string
- // Indexes is the set of indexes for querying this table. The key
- // is a unique name for the index and must match the Name in the
- // IndexSchema.
- Indexes map[string]*IndexSchema
- }
- // Validate is used to validate the table schema
- func (s *TableSchema) Validate() error {
- if s.Name == "" {
- return fmt.Errorf("missing table name")
- }
- if len(s.Indexes) == 0 {
- return fmt.Errorf("missing table indexes for '%s'", s.Name)
- }
- if _, ok := s.Indexes["id"]; !ok {
- return fmt.Errorf("must have id index")
- }
- if !s.Indexes["id"].Unique {
- return fmt.Errorf("id index must be unique")
- }
- if _, ok := s.Indexes["id"].Indexer.(SingleIndexer); !ok {
- return fmt.Errorf("id index must be a SingleIndexer")
- }
- for name, index := range s.Indexes {
- if name != index.Name {
- return fmt.Errorf("index name mis-match for '%s'", name)
- }
- if err := index.Validate(); err != nil {
- return fmt.Errorf("index %q: %s", name, err)
- }
- }
- return nil
- }
- // IndexSchema is the schema for an index. An index defines how a table is
- // queried.
- type IndexSchema struct {
- // Name of the index. This must be unique among a tables set of indexes.
- // This must match the key in the map of Indexes for a TableSchema.
- Name string
- // AllowMissing if true ignores this index if it doesn't produce a
- // value. For example, an index that extracts a field that doesn't
- // exist from a structure.
- AllowMissing bool
- Unique bool
- Indexer Indexer
- }
- func (s *IndexSchema) Validate() error {
- if s.Name == "" {
- return fmt.Errorf("missing index name")
- }
- if s.Indexer == nil {
- return fmt.Errorf("missing index function for '%s'", s.Name)
- }
- switch s.Indexer.(type) {
- case SingleIndexer:
- case MultiIndexer:
- default:
- return fmt.Errorf("indexer for '%s' must be a SingleIndexer or MultiIndexer", s.Name)
- }
- return nil
- }
|