Subject: [YANG] deep keys and unique statements

From: Andy Bierman <[email-masked]>
Date: Fri, 18 Jan 2008 08:23:21 -0800

Hi,

I share Ladislav's concern that YANG requires all key components
to be leafs at the very top-level within the list.

IMO, there is no harm or massive complexity introduced if
a key leaf is allowed to be nested within N containers.
A key must be mandatory, and have only one instance per list entry,
therefore nested lists or choices cannot contain key leafs.

This 'container only' is not a CLR -- just the properties of a key.
The implementation burden of buffering input does not seem
that important, since key leafs can appear anywhere in list,
and there may be a lot of XML-on-the-wire before the key leaf
shows up.  Key components do not have to be used in 'XML order'
either, which also requires buffering to support.

On the other hand, the unique-stmt allows arbitrary combinations
of leaf instances anywhere within the list.  The complexity
built into the unique-stmt is extensive, as even a 2-d table shows:

   list foo {
     // all nodes except the key leafs (x, c, d) are optional
     config true;
     key x;
     unique "y bar/a baz/e baz/c";

     list bar {
       config false;
       leaf a { type int32; }
       leaf b { type string; }
     }

     list baz {
       key "d c";
       leaf c { type float32; }
       leaf d { type float64; }
       leaf e { type binary; }
     }

     leaf x { type instance-identifier; }
     leaf y { type keyref { path "baz/c"; } }

   }

The agent has to check all the instances of all the leafs and only
enforce uniqueness in the entries that are complete.  One missing
optional leaf, and the entire unique-stmt is ignored instead (for that
entry).

Besides this unbounded complexity, it seems very odd for
the leafs within the nested lists (bar and baz) to have
uniqueness constraints placed 'from above', since they are
not required to be unique within the list that defines the leafs.

It also seems broken that config and non-config leafs can be
combined in the uniqueness test.  The 'config' and 'unique'
statements are not relevant in notification data, so is it
an error or just no-op if they are entered for notification
data-def-stmts?  (Could be from uses expansion as well.)
(Note that keyref adds an indirection twist to the complexity.)

Andy

_______________________________________________
YANG mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/yang

---

From: Ladislav Lhotka <[email-masked]>
Date: Mon, 21 Jan 2008 10:05:48 +0100

> built into the unique-stmt is extensive, as even a 2-d table shows:

I am thinking about an alternative "upside-down" implementation of both
key and unique properties, namely to declare these properties with the
leaf. The semantics would be that these properties always pertain to the
nearest ancestor list (if any, otherwise it is noop). Example:

list aaa {
  container bbb {
    leaf c {
      type c-type;
      unique;
    }
  }
}

There are two advantages:
1. The scope of the property - nearest ancestor list - is always unique,
so no XPath expressions are needed here.
2. At the time when the declaration is read the entire ancestor chain is
known, i.e., no buffering is needed.

If I remember correctly, the main objection against this implementation
is that it would be difficult to declare keys a posteriori for standard
groupings, but I think it could be handled by extending the augment
statement, e.g, like this:

module inet-extra {
  ...
  grouping endpoint {
    leaf address {
      type inet:address;
    }
    leaf port {
      type uint16;
    }
  }
  ...

import inet-extra {
  prefix iex;
}

augment "/iex:endpoint/iex:address" {
  key;
}

Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

---

From: Martin Bjorklund <[email-masked]>
Date: Mon, 21 Jan 2008 10:17:27 +0100 (CET)

> nearest ancestor list (if any, otherwise it is noop). Example:

This doesn't work if it is the combination of two leafs that is
unique.  In this example, the name has to be unique, and also the
ip/port combination:

  list server {
    key "idx";
    unique "ip port";
    unique "name";

    leaf idx { ... }
    leaf ip { ... }
    leaf port { ... }
    leaf name { ... }
  }

[Side note: In our current DML we took the approach you describe, but
in order to handle the combinations, the unique statement took an
argument which was a tag.  All leafs with the same tag would be
checked in combination.  I think the YANG statement is more clear.]

> known, i.e., no buffering is needed.

I don't understand these advantages.  Are you talking about buffering
in the compiler?

> statement, e.g, like this:

I think it would be the uses refinement that would be used (not augment):

  list foo {
    uses iex:endpoint {
      leaf address {
        key true;
      }
    }
  }

/martin

---

From: Ladislav Lhotka <[email-masked]>
Date: Mon, 21 Jan 2008 11:20:27 +0100

> unique.  In this example, the name has to be unique, and also the

In RELAX NG we enclose the two elements in a group pattern and attach
the property to that group. Perhaps grouping statement could be used for
this purpose in YANG?

> I don't understand these advantages.  Are you talking about buffering

I mean this: If the validator is checking a configuration value and
finds in the schema that it is declared as unique, it can immediately
tell whether the value is unique within the configuration read so far.
In a YANG-like implementation with deep keys, it would have to buffer
all unique declarations as long as it is inside the list and determine
first for each leaf instance in the configuration whether it was
previously declared as unique. I assume the validator walks down the
hierarchies of configuration data and the schema in parallel, it may not
be an issue if you compile the schema into another representation.
 
> I think it would be the uses refinement that would be used (not augment):
Yes, this looks nice.

Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C