ycl eav, by
PYK, is an entity-attribute-value system for Tcl, built upon
sqlite, that features a Tcl-ish interface and query capabilities, traces for maintaining constraints on data and reacting in other ways to record updates, and the ability to traverse logical
hierarchies in the data.
Description edit
In an entity-attribute-value system, structure that might otherwise be found in the database schema is in the data instead.
ycl eav provides the features needed to store data in this fashion and to use it as if it were structured into a more traditional relational schema.
An entity-attribute value system easily accomodates hierarchical data such as that represented by
XML documents. Nodes in logical hierarchies within a dataset can be discovered using
eav find. See below for more information.
As a rule,
eav routines process records in the order they were entered. This makes it possible to view a snapshot of the data by limiting results to records that preceded some particular record.
Documentation edit
- The source code
- Includes documentation in prose.
Creating an Eav edit
eav myeav filename /path/to/some/file
If no filename is provided, the database is created in memory
eav myeav
Creating Entities edit
To create a new entity, assign one or more attributes and provide the
empty string as the entity identifier:
set hydrogen [myeav set {} name hydrogen protons 1]
set oxygen [myeav set {} name oxygen protons 8 phase gas]
set sodium [myeav set {} name sodium protons 11 phase solid]
Removing Entities edit
To remove an entity:
myeav unset $oxygen
Copying Entities edit
To copy an entity:
myeav set {} {*}[myeav get $oxygen]
Adding Attributes edit
To set an additional attribute on an entity:
myeav set $hydrogen phase gas
To add multiple records for an attribute, use
insert instead of
setset water [myeav set {} component $hydrogen]
$water insert component $oxygen
Removing Attributes edit
To unset all records of
$oxygen where the attribute is "protons":
myeav unset $oxygen protons
Modifying Attribute Values edit
To change the value of the last record for some attribute:
myeav set $entity $attribute $value
To increment by 3 the value of the last record for some attribute:
myeav incr $entity $attribute 3
Retrieving Values edit
To retrieve the value of an attribute, use
setmyeav set $hydrogen component
To retrieve a dictionary of selected values of a entity:
myeav get $hydrogen protons phase
To check if an attribute exists for some entity:
myeav exists $hydrogen phase
If an entity has multiple values for an attribute, only the last value is returned.
To retrieve a list of selected values for an attribute:
myeav list $hydrogen protons phase
Ensuring Such an Entity edit
To ensure that an entity having a certain profile (set of attributes and associated values) exists:
set nitrogen [myeav ensure name nitrogen protons 7]
Nested Dictionaries edit
dset,
dget, and
dexists make it possible to process
eav records as
nested dictionaries:
set Cronus [myeav set {} name Cronus]
set Apollo [myeav set {} name Apollo]
myeav dset [list $Cronus sons Zeus sons] Apollo $Apollo
puts [myeav dset [list $Cronus sons Zeus sons Apollo] name]
Finding Entities edit
The first argument to
find is a list of attributes to include in the results, and the remaining arguments are operators and their arguments. Each operator consumes a certain number of arguments, and any subsequent argument is another operator. If all operations are true for some entity, it is included in the result set.
To find the entity identifiers for all entities that have a "phase" attribute:
myeav find {} exists phase
To retrieve a dictionary, keyed by identifier, of all entities that have a "phase" attribute:
myeav find * exists phase
To retrieve only the "protons" and "phase" attributes of such entities:
myeav find {protons phase} exists phase exists protons
But since any attribute mentioned in the first argument implies an "exists" requirement, the previous command is equivalent to:
myeav find {protons phase}
To find entities that have at least 3 protons:
myeav find {} > protons 3
To find the names of entities that have at least 3 protons and a phase of "solid":
myeav find name > protons 3 == phase solid
To find entities that are missing some attribute:
myeav find name > protons 3 is missing phase
To limit results to those that were inserted prior to some record, use the
id operator:
myeav find {} id < $id
Finding Members of Logical Hierarchies edit
To find members of logical hierarchies of entities, use the
descend operator, which takes the name of an entity to build the hierarchy on, and either an
== or an
entity operation that selects the entry points into the hierarchy, as well as provides the criteria for selecting children of the current node in the hierarchy. For example with an eav instance named
organization:
organization find {} descend boss entity == $myboss
To use a set of criteria instead of an entity to specifiy the entry point(s) into the hierarchy:
organization find {} descend boss name == Neo
The eval operator edit
find features an
eval operator that functions just like the one in the Tcli interface to
sqlite:
organization find {} entity == $myboss descend boss eval record {
puts [array get $record]
}
Ordering Results edit
find usually processes data in the order of insertion. To change this order, use the
order operation:
myeav find {} order value
union takes a list of arguments that might be passed to
find, and wraps them up into a single database query. for operators that only make sense when given once, the last occurrence is used.
Example:
myeav union {* protons > 3} {* missing phase eval record {
puts [array get record]
}}
Both write and unset actions can be traced. A trace can specify an attribute, an entity, or both. This results in four kinds of traces:
- Any attribute of any entity.
- Any attribute of a particular entity.
- A particular attribute of any entity.
- A particular attribute of a particular entity.
All traces that match fire, with more general matches firing first. To set a trace:
myeav trace write $id $attribute_name $cmdPrefix
The command prefix has the following signature:
operation entity attribute value
$operation is one of
write or
unset.