Subject: [netmod] empty leaf as key

From: Martin Bjorklund <[email-masked]>
Date: Wed, 10 Sep 2008 12:48:19 +0200 (CEST)

Hi,

At the FAQ sprint yesterday the question came up why leafs of type
empty are not allowed as keys.

It was late and obviously I wasn't thinking properly when I said that
it should be allowed...

The reason this is not allowed is that an empty leaf has no extra
information than its existance; an empty leaf can exist or not exist.
If it exists, there is no additional data associated with it.  And key
leafs MUST exist.  So if we allow empty leafs in keys, we add no
information at all to the key - the empty leaf must be present in all
instances, it cannot be deleted, and it contains no info.

/martin
_______________________________________________
netmod mailing list
[email-masked]
https://www.ietf.org/mailman/listinfo/netmod

---

From: Ladislav Lhotka <[email-masked]>
Date: Wed, 10 Sep 2008 13:31:26 +0200

> instances, it cannot be deleted, and it contains no info.

I don't think this is very important but anyway:

1. You can use keys whose datatypes are restricted to a single value, so
in practice it is the same case. It just means the list can have no more
than one item. If one uses a boolean key, it can have only two items, so
what?

2. During the development and tests of a module and application, it
might be handy to define the key temporarily as empty as a placeholder
so that it exists and can be referred to in keyrefs.

3. No confusion can arise for both the user and system, so I don't see a
reason for banning it explicitly.

Lada
-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

---

From: Phil Shafer <[email-masked]>
Date: Wed, 10 Sep 2008 08:18:46 -0400

>I don't think this is very important but anyway:

If it's not important, can we just leave it as it?

>than one item. If one uses a boolean key, it can have only two items, so

We try to design the language to help people to the right thing and
keep them from doing the wrong thing.   An empty key is never the
right thing, so we don't allow it.

>so that it exists and can be referred to in keyrefs.

Use "type string" as a placeholder.

Thanks,
 Phil

---

From: Ladislav Lhotka <[email-masked]>
Date: Wed, 10 Sep 2008 15:41:59 +0200

> If it's not important, can we just leave it as it?

Yes, but the FAQ question has to be answered. Otherwise it could be
deleted.

> right thing, so we don't allow it.

If empty was allowed and the draft didn't mention it, I am absolutely
sure it would never pop up as a problem or FAQ question. By mentioning
it, this trivial issue gains importance. I see it as a premature
optimization, or CLR.

BTW, the draft says: 'A leaf that is part of the key can be of any
built-in or derived type, except it MUST NOT be the built-in type
"empty".' So is it OK if I use a type derived from empty as a key?

Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Wed, 10 Sep 2008 16:19:13 +0200

On Wed, Sep 10, 2008 at 03:41:59PM +0200, Ladislav Lhotka wrote:

OLD:

   A leaf that is part of the key can be of any built-in or derived
   type, except it MUST NOT be the built-in type "empty".

NEW 1:
   A leaf that is part of the key can be of any built-in or derived
   type. Note that leafs using a type allowing only a single value
   (e.g. the built-in type empty) are not useful as part of a key.

NEW 2:
   A leaf that is part of the key can be of any built-in or derived
   type.

Which do you want Lada?

/js

-- 
Juergen Schoenwaelder           Jacobs University Bremen gGmbH
Phone: +49 421 200 3587         Campus Ring 1, 28759 Bremen, Germany
Fax:   +49 421 200 3103         <http://www.jacobs-university.de/>
_______________________________________________
netmod mailing list
[email-masked]
https://www.ietf.org/mailman/listinfo/netmod

---

From: Ladislav Lhotka <[email-masked]>
Date: Wed, 10 Sep 2008 16:35:27 +0200

>    A leaf that is part of the key can be of any built-in or derived

Both NEW 1 and 2 are fine, I slightly prefer 2 since it is simple and
straightforward and everything will work quite predictably.

Lada
 
-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

---

From: Andy Bierman <[email-masked]>
Date: Wed, 10 Sep 2008 08:10:23 -0700

>>    (e.g. the built-in type empty) are not useful as part of a key.

There is a big difference between an enumeration as a key
which happens to only have one enum value assigned so far,
and an 'empty' as a key, which can never have a 2nd value added.

IMO, the fix is simply:

OLD:

  ... MUST NOT be the built-in type "empty".

NEW:

  ... MUST NOT be the built-in type "empty", or any type
  derived from the built-in type "empty".

> straightforward and everything will work quite predictably.

Andy

---

From: Phil Shafer <[email-masked]>
Date: Wed, 10 Sep 2008 11:38:04 -0400

>it, this trivial issue gains importance. I see it as a premature

I see it as a code path I don't need to write/test/maintain, as
a mistake a compiler can catch, and as a source of incompatibilities
between tools sets (where many tools won't test such an odd scenario).
Making it illegal hurts no one.

Thanks,
 Phil

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Thu, 11 Sep 2008 00:52:00 +0200

On Wed, Sep 10, 2008 at 08:10:23AM -0700, Andy Bierman wrote:
> Ladislav Lhotka wrote:
>> Juergen Schoenwaelder p????e v St 10. 09. 2008 v 16:19 +0200:

Well, this is still kind of arbitrary. There are other ways to define
leafs that do not make sense as keys in YANG:

    leaf a { type string { length 0; } }

    leaf b { type int32 { range "0..0"; } }

Right now all of these definitions seem to be legal but they are also
pretty pointless. Shall we now add language for all these constructs
that are pointless to forbid them? I don't think so - it is way too
risky to screw this up. I would leave it to implementations to catch
such things and to produce proper warnings. So I am slowly moving into
Lada's camp:

/js

PS: I am not sure whether 8.1.3 allows this or not:

    typedef c { type int32 { range "0..1"; } }
    leaf d { type c { range "1..2"; } }

    I also do not see why the third example in 8.1.4 is illegal.

---

From: Andy Bierman <[email-masked]>
Date: Wed, 10 Sep 2008 16:51:05 -0700

>    A leaf that is part of the key can be of any built-in or derived

I disagree with you and Lada, and agree with Phil instead ;-)
There are lots of rules/decisions in YANG that are intended
to yield better data modeling practices.

The problem with 'NEW 1' above is that tools MUST support
empty as a key.  Saying that an empty leaf is not useful
as a key does not help very much.

A leaf specified in the key must always be present,
and any default is ignored.  Therefore, a key which
can only ever have 1 value seems to be a waste of space.

This is a pretty big pile of "garbage-in/garbage-out"
to add to the language.

How do I specify empty in a predicate in an instance-identifier?
It it just '' (e.g., /foo[emptykey='']/bar), even
though the empty data type is not a string?
(so maybe a tool that sees 'emptykey=value' will trigger
an error since any value for 'emptykey' is an error?)

Andy

---

From: Andy Bierman <[email-masked]>
Date: Wed, 10 Sep 2008 18:16:55 -0700

>..

this is not allowed.
you can only refine a range (8.1.3, para 2, s3)

>     I also do not see why the third example in 8.1.4 is illegal.

probably because it isn't :-)  there's a bug in the example:

OLD:

      type int32 {
          // illegal range restriction
          range "11..100";
      }

NEW:

      type my-base-int32-type {
          // illegal range restriction
          range "11..100";
      }

Andy

---

From: Ladislav Lhotka <[email-masked]>
Date: Thu, 11 Sep 2008 08:22:18 +0200

> can only ever have 1 value seems to be a waste of space.

This is all true, but why is it a problem that YANG or any tools must
explicitly avoid? The empty key leaf will be present and adds no
variability to the key, so it is pointless but consistent.

I understand that programming and database languages may not have an
empty type but it should be easy to emulate it if necessary.

> This is a pretty big pile of "garbage-in/garbage-out"

I actually see less garbage in the language definition.

> It it just '' (e.g., /foo[emptykey='']/bar), even

This will work in XPath (but with all three QNames having namespace
prefixes!:-) since in XML a leaf with empty type in indistinguishable
from 'type string { length 0; }'. Or you can use 

/foo[emptykey]/bar 

Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Thu, 11 Sep 2008 08:35:05 +0200

> >     I also do not see why the third example in 8.1.4 is illegal.

So is the following valid then?

	  typedef d { type int32 { range "0..3|5..7"; } }
	  typedef e { type d { range "3..6"; } }

/js

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Thu, 11 Sep 2008 08:44:45 +0200

> as a key does not help very much.

But the handling of empty as a key should fall out naturally. You can
always emulate empty with string { length 0; } anyways so I am not
sure what the code saving is here.
 
> can only ever have 1 value seems to be a waste of space.

No question about that. But there are many ways to do stupid things in
YANG and trying to catch everything and marking things as an _error_
makes a language complicated and you take a serious risk to shoot
yourself into the foot by putting in a rule with best intentions that
later bites you. For me, simplicity usually comes from orthogonality
where things fall out naturally.

/js

---

From: Martin Bjorklund <[email-masked]>
Date: Thu, 11 Sep 2008 09:01:09 +0200 (CEST)

>           // illegal range restriction

Thanks, fixed.

/martin

---

From: Balazs Lengyel <[email-masked]>
Date: Thu, 11 Sep 2008 09:28:04 +0200

> 	  typedef e { type d { range "3..6"; } }
IMO it is invalid. Any construct that adds even one single additional value to the value-space 
of a type is illegal (here the value 4). You should be able to be more restrictive but never to 
allow new values.
Balazs
_______________________________________________
netmod mailing list
[email-masked]
https://www.ietf.org/mailman/listinfo/netmod

---

From: Andy Bierman <[email-masked]>
Date: Thu, 11 Sep 2008 00:42:23 -0700

> 	  typedef e { type d { range "3..6"; } }

no - read sec 8.1.3, 2nd paragraph, 3rd sentence

Andy

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Thu, 11 Sep 2008 09:51:31 +0200

> IMO it is invalid. Any construct that adds even one single
> additional value to the value-space of a type is illegal (here the
> value 4). You should be able to be more restrictive but never to
> allow new values.

I agree - but then the example is not adding something according to my
interpretation - I assumed the resulting value set is {3, 5, 6}. With
pattern, we can effectively do the same - a pattern of a sub-type must
be satisfied in addition to the pattern of the parent type.

The question is whether the above is illegal and I would be forced to
write "3|5..6". And I note again that with pattern we do not have
constraints how they must be formed relative to each other when we
apply them.

The point really is that the value space can't increase by subtyping.
But instead of saying that, we try to restrict the ranges syntax one
is allowed to use and since this is hard to do and not really useful
for pattern we don't do this for pattern. This is not very consistent.

The other question is how we deal with restrictions that lead to an
empty value set, e.g.:

      typedef f { type string { pattern "a"; } }
      typedef g { type f { pattern "b"; } }
      typedef h { type f { length 2; } }

[With real world pattern that are several lines long, things like this
 might not always be obvious and easy to spot.]

I think we need to spell out constraints in terms of the value set
rather than the syntactic means of the restrictions. And I don't think
we will succeed to mark all these things illegal by adding language
rules to YANG without causing damage to the language. So we have to
leave some of this to implementations to figure out what they can
catch as warnings.

/js

---

From: Balazs Lengyel <[email-masked]>
Date: Thu, 11 Sep 2008 10:32:02 +0200

I agree that we should state "the value space can't increase by subtyping" as a basic rule.
However we must also explicitly state whether this 3..6 will include 4 or not, (not trivial), 
so are all constraints in the type chain to be considered or just the last one which must be 
valid according to the basic rule.

I would not be too worried about empty value spaces. They are just one of the ways to shoot 
yourself. Maybe add: "An implementation MAY consider a data type that has an empty value space 
as a YANG error."
Balazs

-- 
Balazs Lengyel                       Ericsson Hungary Ltd.
TSP System Manager
ECN: 831 7320                        Fax: +36 1 4377792
Tel: +36-1-437-7320     email: [email-masked]
_______________________________________________
netmod mailing list
[email-masked]
https://www.ietf.org/mailman/listinfo/netmod

---

From: Martin Bjorklund <[email-masked]>
Date: Thu, 11 Sep 2008 13:00:45 +0200 (CEST)

> for pattern we don't do this for pattern. This is not very consistent.

I agree, it's not consistent.  The text for range handling comes from
SMIng, which didn't have patterns.  From a reader's perspective I
think it would be better if both ranges and patterns were restricted
this way.  But you're right that it is difficult to check.

> rather than the syntactic means of the restrictions.

Yes, unfortunately.

/martin

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Thu, 11 Sep 2008 14:10:19 +0200

On Thu, Sep 11, 2008 at 10:32:02AM +0200, Balazs Lengyel wrote:

> I agree that we should state "the value space can't increase by
> subtyping" as a basic rule.  However we must also explicitly state
> whether this 3..6 will include 4 or not, (not trivial), so are all
> constraints in the type chain to be considered or just the last one
> which must be valid according to the basic rule.

I think all restrictions on the type chain must be considered and be
valid. This is what we assume for pattern.

/js

---

From: Phil Shafer <[email-masked]>
Date: Thu, 11 Sep 2008 10:08:42 -0400

Juergen Schoenwaelder writes:
>risky to screw this up.

We can't stop people from going down paths that are broken or
pointless, but we can certainly stop them when their very first
step is pointless.

Thanks,
 Phil

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Thu, 11 Sep 2008 20:10:39 +0200

> pointless, but we can certainly stop them when their very first

But you make assumptions that they are _always_ pointless and this is
where the risk it. Let me try to make a hypothetical argument: Suppose
someone needs to translate to/from some proprietary language which
always requires that keys have three components. In cases where the
key is a simple value, you would love to use type empty leafs to fill
the other two required elements but you can't; you have to hack away
with something that is an empty string.

Perhaps this isn't a very convincing example. But the risk that
special rules invented with the best intentions can back fire is
there.

/js

---

From: Phil Shafer <[email-masked]>
Date: Thu, 11 Sep 2008 14:39:04 -0400

>special rules invented with the best intentions can back fire is

Sure. I'm just all for helping the user (the modeler) do the right
thing the first time.  It will help their experience with YANG and
help the quality of YANG models.  Yes, compilers can give warnings
for errors like this, but warnings are largely ignored until someone
decides to turn on -Werror.  I'd like to have -Werror set from the
start.

Thanks,
 Phil

---

From: Ladislav Lhotka <[email-masked]>
Date: Thu, 11 Sep 2008 20:56:42 +0200

> thing the first time.  It will help their experience with YANG and

I cannot imagine how a poor user could ever come up with the idea of
using empty type for a key leaf. Why could he assume that it could be
useful in any way? It can be only because it's forbidden in the draft
that he might be tempted to test it. Otherwise, the empty key can IMO
only appear in test suites and urban legends.

Or, maybe, there actually is a reasonable case that we fail to see now,
as Juergen points out.

Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

---

From: Andy Bierman <[email-masked]>
Date: Fri, 12 Sep 2008 17:26:01 -0700

>>> 	  typedef e { type d { range "3..6"; } }

The agreement reached in the YANG design team was that
the new range cannot add values, just restrict values,
so 'e' is invalid because it adds '4' to the range.

Unlike patterns which are ANDed together,
only the 'closest' range to the leaf definition
is used.  The user has to type 'range "3 | 5..6"'
for this definition to be valid.

> be satisfied in addition to the pattern of the parent type.

It could be interpreted differently for a range because
it is a true restriction, not 1 term in an AND expression.
All the numbers in the new range must be valid within
its parent range (if any).  IMO this is easy to implement,
and easy to understand.

> >...

Andy

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Sat, 13 Sep 2008 08:56:51 +0200

> its parent range (if any).  IMO this is easy to implement,

So you think it is a design feature to treat range restrictions
different than other type restrictions, e.g. combinations of length
and pattern or pattern and pattern restrictions?

/js

---

From: Andy Bierman <[email-masked]>
Date: Sat, 13 Sep 2008 02:06:08 -0700

> and pattern or pattern and pattern restrictions?

There are lots of properties that are determined in lots
of ways, like default and mandatory and config and min-elements, etc.
The AND expression for patterns is the exception, not the rule.

Andy

---

From: Martin Bjorklund <[email-masked]>
Date: Mon, 15 Sep 2008 09:42:21 +0200 (CEST)

> the new range cannot add values, just restrict values,

I don't think this principle is questioned in this thread.

> so 'e' is invalid because it adds '4' to the range.

Since 'd' defines the value space { 0 1 2 3 5 6 7 }, 'e' above
restricts this to the subset { 3 5 6 }

Compare with

  typedef ds { type string { pattern "[0-3]|[5-7]"; } }
  typedef es { type ds { pattern "[3-6]"; } }

which is legal YANG.

Why should range and pattern behave differently?  This is just
confusing to the user.  (when do I have to repeat the restrictions?)

I like the current way of handling ranges, since it is very explicit.
The user just has to read one range expression to understand the
type.  With patterns, the user has to follow the type chain.

It would be nicest if we could use the same rule for patterns, but
since this is very difficult (impossible?) for tools to check, we
can't do that.

But I prefer to have consistent rules.  The user should know what to
expect from a type derivation.  So I think we should change the rules
for range to match the rules for pattern.

/martin