Example #1
0
//
// Create an index given the name (index) and a list of field positions
// used to create a composite key.
//
// nilFirst specifies if nil values should sort first (lowest possible value) or last (highest possible value)
//
// The field position should corrispond to the entries in DataRecord ToFieldList() and FromFieldList()
//
func (t *Table) CreateIndex(index string, nilFirst bool, fields ...uint64) error {
	db := (*bolt.DB)(t.d)

	err := db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket(schema(t.name))
		if b == nil {
			return NO_TABLE
		}

		b1, err := typedbuffer.Encode(nilFirst)
		if err != nil {
			return BAD_VALUES
		}
		b2, err := typedbuffer.Encode(fields)
		if err != nil {
			return BAD_VALUES
		}

		enc := append(b1, b2...)
		if err := b.Put([]byte(index), enc); err != nil {
			return err
		}

		if _, err := tx.CreateBucket(indices(index)); err != nil {
			return err
		}

		return nil
	})

	if err == nil {
		t.indices[index] = indexinfo{
			nilFirst: nilFirst,
			iplist:   makeIndexPos(fields),
		}
	}

	return err
}
Example #2
0
//
// Delete a record from the table, given the index and the key
//
func (t *Table) Delete(index string, key DataRecord) error {
	db := (*bolt.DB)(t.d)

	err := db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket(indices(index))
		if b == nil {
			return NO_INDEX
		}

		info := t.indices[index]

		sk, _, err := info.marshalKeyValue(key.ToFieldList())
		if err != nil {
			return err
		}

		if sk == nil {
			return NO_KEY
		}

		c := b.Cursor()
		k, v := c.Seek(sk)

		// Seek will return the next key if there is no match
		// so make sure we check we got the right record

		if bytes.Equal(sk, k) {
			if err := c.Delete(); err != nil {
				return err
			}

			fields, err := info.unmarshalKeyValue(k, v)
			if err != nil {
				return err
			}

			for i, info := range t.indices {
				if i == index {
					// already done
					continue
				}

				b := tx.Bucket(indices(i))
				if b == nil {
					continue
				}

				// could use marshalKeyValue() instead

				vkey := make([]interface{}, len(info.iplist))
				for _, ip := range info.iplist {
					vkey[ip.pos] = fields[ip.field]
				}

				dkey, err := typedbuffer.Encode(vkey...)
				if err != nil {
					return err
				}

				if err := b.Delete(dkey); err != nil {
					return err
				}
			}
		}

		return nil
	})

	return err
}