Fyi using the RANK operator with a rva

This forum is for any questions about the language Tutorial D or the Rel implementation of it.
Post Reply
steved
Posts: 49
Joined: Sun Sep 01, 2013 10:53 pm

Fyi using the RANK operator with a rva

Post by steved » Fri Aug 17, 2018 4:51 am

The RANK operator is extremely useful especially when used with rva's (relation valued attributes).
But in this context you have to be careful.
For example, given this relation:

Code: Select all

 REL{TUP{KEY. 1,ID "A"},
     TUP{KEY. 2,ID "A"}, 
     TUP{KEY. 3,ID "B"},
     TUP{KEY. 4,ID "B"},
     TUP{KEY. 5,ID "B"}} 
Suppose you want to GROUP attribute KEY. over attribute ID and create attribute RANK. using
attribute KEY. for the ranks. You want to end up with the following result (or at least close to it):

Code: Select all

RELATION {ID CHARACTER, GRP.RVA RELATION {KEY. INTEGER}, RANKS.RVA RELATION {KEY. INTEGER, RANK. INTEGER}} {
     TUPLE {ID "A", GRP.RVA RELATION {KEY. INTEGER} {
     TUPLE {KEY. 1},
     TUPLE {KEY. 2}
}, RANKS.RVA RELATION {KEY. INTEGER, RANK. INTEGER} {
     TUPLE {KEY. 1, RANK. 1},
     TUPLE {KEY. 2, RANK. 2}
}},
     TUPLE {ID "B", GRP.RVA RELATION {KEY. INTEGER} {
     TUPLE {KEY. 3},
     TUPLE {KEY. 4},
     TUPLE {KEY. 5}
}, RANKS.RVA RELATION {KEY. INTEGER, RANK. INTEGER} {
     TUPLE {KEY. 3, RANK. 1},
     TUPLE {KEY. 4, RANK. 2},
     TUPLE {KEY. 5, RANK. 3}
}}
}
Rva GRP.RVA is the result of GROUP using KEY. and rva RANKS.RVA is the relation with KEY.
and the rank attribute RANK.
You might think this query should do it:

Code: Select all

REL{TUP{KEY. 1,ID "A"},
    TUP{KEY. 2,ID "A"}, 
    TUP{KEY. 3,ID "B"},
    TUP{KEY. 4,ID "B"},
    TUP{KEY. 5,ID "B"}} 
    GROUP{KEY.} AS GRP.RVA 
    EXTEND {RANKS.RVA:=GRP.RVA{KEY.} RANK(ASC KEY. AS RANK.)}    
But if you execute the query you will get a fatal exception. The salient part of the error is this:

Code: Select all

org.reldb.rel.exceptions.ExceptionFatal: RS0452: Bad tuple. Heading TUPLE {KEY. INTEGER, RANK. INTEGER} says degree = 2 but tuple TUPLE {1} says degree = 1.
This error suggests that Rel can't determine the attribute(s) in rva GRP.RVA. GRP.RVA was initially
defined with just attribute KEY. but the ranking implies attributes KEY. and RANK. so which definition
should be used (perhaps Rel is also ignoring the relevance of RANKS.RVA which is where attribute RANK.
belongs).
In any case there are some simple ways to remove any ambiguities and get the query working.
One way is to show the degree of GROUP.RVA consistently. The degree of GROUP.RVA is 1 when its
formed so use a projection(with KEY.) with it in RANKS.RVA so the degree is always 1.

Code: Select all

REL{TUP{KEY. 1,ID "A"},
    TUP{KEY. 2,ID "A"}, 
    TUP{KEY. 3,ID "B"},
    TUP{KEY. 4,ID "B"},
    TUP{KEY. 5,ID "B"}} 
    GROUP{KEY.} AS GRP.RVA 
    EXTEND {RANKS.RVA:=GRP.RVA{KEY.} RANK(ASC KEY. AS RANK.)}
This query returns the result mentioned above.
Another way is to simply remove GRP.RVA from the result.

Code: Select all

(REL{TUP{KEY. 1,ID "A"},
    TUP{KEY. 2,ID "A"}, 
    TUP{KEY. 3,ID "B"},
    TUP{KEY. 4,ID "B"},
    TUP{KEY. 5,ID "B"}} 
    GROUP{KEY.} AS GRP.RVA 
    EXTEND {RANKS.RVA:=GRP.RVA RANK(ASC KEY. AS RANK.) }){ALL BUT GRP.RVA} 
This query returns just ID and RANKS.RVA and may be more appropriate when GRP.RVA is no longer needed.

Code: Select all

RELATION {ID CHARACTER, RANKS.RVA RELATION {KEY. INTEGER, RANK. INTEGER}} {
     TUPLE {ID "A", RANKS.RVA RELATION {KEY. INTEGER, RANK. INTEGER} {
     TUPLE {KEY. 1, RANK. 1},
     TUPLE {KEY. 2, RANK. 2}
}},
     TUPLE {ID "B", RANKS.RVA RELATION {KEY. INTEGER, RANK. INTEGER} {
     TUPLE {KEY. 3, RANK. 1},
     TUPLE {KEY. 4, RANK. 2},
     TUPLE {KEY. 5, RANK. 3}
}}
}
Also if you put a query with this error in an operator the operator will compile
with the error hidden until the operator is executed.

Dave
Site Admin
Posts: 364
Joined: Sun Nov 27, 2005 7:19 pm

Re: Fyi using the RANK operator with a rva

Post by Dave » Fri Aug 17, 2018 7:28 am

You mentioned this causes a fatal error?

Code: Select all

REL{TUP{KEY. 1,ID "A"},
    TUP{KEY. 2,ID "A"}, 
    TUP{KEY. 3,ID "B"},
    TUP{KEY. 4,ID "B"},
    TUP{KEY. 5,ID "B"}} 
    GROUP{KEY.} AS GRP.RVA 
    EXTEND {RANKS.RVA:=GRP.RVA{KEY.} RANK(ASC KEY. AS RANK.)}    
I tried it and it works.

steved
Posts: 49
Joined: Sun Sep 01, 2013 10:53 pm

Re: Fyi using the RANK operator with a rva

Post by steved » Fri Aug 17, 2018 7:35 am

My mistake. This query, without the projection on GRP.RVA, will cause a fatal error:

Code: Select all

REL{TUP{KEY. 1,ID "A"},
    TUP{KEY. 2,ID "A"}, 
    TUP{KEY. 3,ID "B"},
    TUP{KEY. 4,ID "B"},
    TUP{KEY. 5,ID "B"}} 
    GROUP{KEY.} AS GRP.RVA 
    EXTEND {RANKS.RVA:=GRP.RVA RANK(ASC KEY. AS RANK.)}    

Dave
Site Admin
Posts: 364
Joined: Sun Nov 27, 2005 7:19 pm

Re: Fyi using the RANK operator with a rva

Post by Dave » Fri Aug 17, 2018 2:54 pm

Looks like an even simpler example exhibits this bug.

This throws the fatal error:

Code: Select all

RELATION {TUPLE {RVA RELATION {TUPLE {K 1}}}} EXTEND {RR := RVA RANK (ASC K AS R)}
This works:

Code: Select all

RELATION {TUPLE {RVA RELATION {TUPLE {K 1}}}} EXTEND {RR := RVA {K} RANK (ASC K AS R)}
I've noted this in my "to do" list.

Post Reply