Webrel is an educational, web-based integrated development environment (IDE) and interpreter for Relational Algebra. It specifically follows the notation and theory established by C.J. Date and is designed to help students visualize database operations.
Originally developed as a portable tool, it is now hosted on Launchpad .
- Zero Installation: Built entirely with XHTML and JavaScript, it runs in any standard web browser without additional software
- LALR Parsing: Utilizes a robust LALR parser for high flexibility and standard compliance.
- Visual Debugging Mode: A unique "Debug" feature shows the step-by-step execution of internal operations as separate tables.
- Simplified Syntax: While maintaining compatibility with relational standards, the grammar is optimized for educational clarity based on reference textbooks.
- Built-in Datasets: Includes common educational databases (like Suppliers and Parts) to allow immediate testing.
The interpreter supports a core subset of relational algebra commands:
- Selection (WHERE)
- Projection ({...})
- Join (JOIN) and Divide (DIVIDEBY)
- Set Operations: UNION, INTERSECT, MINUS, and TIMES
- Specialized Operators: RENAME, EXTEND, SUMMARIZE, SEMIJOIN, and SEMIMINUS
- Data Updates: INSERT, DELETE, and UPDATE commands
The interpreter follows a standard compiler pipeline implemented in JavaScript:
- Lexical Analyzer: A custom scanner using a state-machine (switch-case) approach to tokenize input.
- Syntactic Analyzer: An LALR parser that manages a state stack and an execution machine.
- Execution Engine: Maps each grammar reduction to a specific function that performs the relational logic.
- UI Engine: An object-oriented table renderer (ColoredTable) that handles the visual display of relations.
- Open https://yoosofan.github.io/webrel/ on any web browser (new or old even IE6).
- Type your query in the text area and click Run.
- Find the names of suppliers
s{sname};
- Find the names and cities of parts
p{pname, city};
- Find the cities of parts and suppliers
p{city} union s{city;
Find the renamed sn as s_num of sp
sp rename (sn as s_num ,pn as p_num);
Find the renamed sn as s_num and pn as p_num of sp
sp rename (sn as s_num ,pn as p_num);
p{pn, pname} times s{sn, sname};((p rename CITY as pcity) times s) where CITY = pcity;(((s rename sn as sa){sa,city} join (s rename sn as sb){sb,city})where sa<sb){sa,sb};((s{sn} minus (sp where pn="P2"){sn}) join s){sname};((sp join s) where pn="P2"){sname};((sp where pn="P2") join s){sname};(s join (sp where pn="P2")){CITY,SNAME,sn,STATUS,pn};(s times (j rename city as jcity))where city=jcity;(((s times (j rename city as jcity))where city <> jcity){sn,jn})join spj{jn};((s join j){sn,jn} join spj){pn};(spj join (s where city="London"){sn}){pn} join p;(p where WEIGHT>12){PNAME}union ((((sp join p)join s) where STATUS>20)join p){PNAME};a:=RELATION {TUPLE{pn pn ("p1")}};b:=RELATION {TUPLE{pn p ("p1")}};a union b;delete s where city="London";s;p1:=relation{tuple{pname("Oscar"),color("blue")}};p1 join p{pname,color};p2:=relation{tuple{color("green"),pname("pn")}};p1 union p2;p8:=relation{tuple{pname("pn1"),color("blue")},
tuple{pname("pn2")},
tuple{pn("p10"),color("red")}};
p8;(spj where qty<>200){qty};p where city="london";with (s rename sn as sa){sa,city} as t1,
(s rename sn as sb){sb,city} as t2,
t1 join t2 as t3,
t3 where sa<sb as t4:
t4{sa,sb};with s{sn} as t1,
sp where pn="P1" as t2,
t2 {sn} as t3,
t1 minus t3 as t4,
t4 join s as t5,
t5{sname} as t6:
t6;s semijoin (sp where pn="P2");s semiminus (sp where pn="P2");s{sn} divideby (sp where sn="s2"){pn} per sp{sn,pn};((s{sn} divideby p{pn} per sp{sn,pn})join s){sname};extend p add weight * 10 as gmwt;(extend p add weight * 10 as GMWT) where COLOR="Red" ;extend s add "suplier" as tag;extend s add ("suplier" as tag , status*5 as jh);extend (p join sp) add weight* 10 as shi;(extend s add city as ccity){All but city};extend s add count ((sp rename sn as x) )as np;summarize sp per p{pn} add sum (QTY) as tq;summarize (p join sp) per p{city} add sum(qty) as nsp;summarize sp per s{sn} add count as np;summarize sp per p{pn} add(sum(qty) as tq1,avg(qty) as tq2);summarize s per s{city} add avg (status) as avg_status;s{sn} divideby (p where color="Red"){pn} per sp{sn,pn};((s{sn} divideby p{pn} per sp{sn,pn})join s){sname};