Kirill Simonov avatar Kirill Simonov committed 47da614

Updated database model reference.

Comments (0)

Files changed (9)

doc/dia/model-and-instance.tex

 \begin{document}
 
 \tikzset{
-    > = stealth',
-    class/.style = {rectangle, text width=2cm, text centered},
-    record/.style = {rectangle, text width=2cm, text centered},
+    > = stealth', shorten > = 1pt, shorten < = 1pt,
+    class/.style = {fill, circle, inner sep=0pt, minimum size=2mm},
+    record/.style = {draw, circle, inner sep=0pt, minimum size=2mm},
     link/.style = {font=\small\itshape},
     envelope/.style = {rectangle, draw=blue!50, rounded corners},
-    envelope header/.style = {font=\bfseries},
+    envelope header/.style = {font=\bfseries\color{blue!75}},
 }
 
 \begin{tikzpicture}
 
-\node[class] (school)
-    {Schools};
-\node[class] (department) [left=3 of school]
-    {Departments};
-\node[class] (program) [below=5 of school.north, anchor=south]
-    {Programs};
-\node[class] (course) [left=3 of program]
-    {Courses};
+\node[class] (school) {};
+\node[class] (department) [left=3 of school] {};
+\node[class] (program) [below=5 of school.north, anchor=south] {};
+\node[class] (course) [left=3 of program] {};
+
+\node[above] (school label) at (school.north)
+    {School};
+\node[above] (department label) at (department.north)
+    {Department};
+\node[below] (program label) at (program.south)
+    {Program};
+\node[below] (course label) at (course.south)
+    {Course};
 
 \draw[->]
     (department)
     to node[link,sloped,above] {offered by}
     (department);
 
-\node[envelope] (model) [fit=(school) (department) (program) (course)] {};
+\node[envelope] (model)
+    [fit=(school label) (department label) (program label) (course label)] {};
 
 \node[envelope header] at (model.north) [above]
     {Model};
 
-\node[record] (comp) [right=1 of school.north east, anchor=north west]
-    {Department of Computer Science};
-\node[record] (ee) [below=5 of comp.north, anchor=south]
-    {Department of Electrical Engineering};
-\node[record] (eng) [right=5 of comp.north, anchor=north]
+\node[record] (comp) [right=4 of school.east, anchor=west] {};
+\node[record] (comp 304) [below=5 of comp.north, anchor=south] {};
+\node[record] (eng) [right=5 of comp.north, anchor=north] {};
+\node[record] (ucompsci) [below=5 of eng.north, anchor=south] {};
+
+\node[record,dotted] [left=0.1 of comp.west] {};
+\node[record,dotted] [left=0.4 of comp.west] {};
+\node[record,dotted] [left=0.1 of comp 304.west] {};
+\node[record,dotted] [left=0.4 of comp 304.west] {};
+\node[record,dotted] [right=0.1 of comp 304.east] {};
+\node[record,dotted] [right=0.4 of comp 304.east] {};
+\node[record,dotted] [right=0.1 of eng.east] {};
+\node[record,dotted] [right=0.4 of eng.east] {};
+\node[record,dotted] [left=0.1 of ucompsci.west] {};
+\node[record,dotted] [left=0.4 of ucompsci.west] {};
+\node[record,dotted] [right=0.1 of ucompsci.east] {};
+\node[record,dotted] [right=0.4 of ucompsci.east] {};
+
+\node[above] (comp label) at (comp.north)
+    {Dept. of Computer Science};
+\node[below] (comp 304 label) at (comp 304.south)
+    {Database Theory};
+\node[above] (eng label) at (eng.north)
     {School of Engineering};
-\node[record] (ucompsci) [below=5 of eng.north, anchor=south]
+\node[below] (ucompsci label) at (ucompsci.south)
     {B.S. in Computer Science};
 
 \draw[->]
     (comp)
-    to node[link,above] {associated with}
+    to node[link,below] {associated with}
     (comp -| eng.west);
 \draw[->]
-    (ee)
-    to node[link,sloped,above] {associated with}
-    (eng);
-\draw[->]
     (ucompsci)
     to node[link,sloped,above] {administered by}
     (eng);
+\draw[->]
+    (comp 304)
+    to node[link,sloped,above] {offered by}
+    (comp);
 
-\node[envelope] (instance) [fit=(eng) (comp) (ee) (ucompsci)] {};
+\node[envelope] (instance)
+    [fit=(eng label) (comp label) (comp 304 label) (ucompsci label)] {};
 
 \node[envelope header] at (instance.north) [above]
     {Instance};

doc/dia/prelude.tex

 \usepackage[landscape]{geometry}
 \usepackage{array}
 \usepackage{tikz}
-\usetikzlibrary{arrows,shapes,positioning,fit,calc}
+\usetikzlibrary{arrows,shapes,positioning,fit,calc,decorations.pathreplacing}
 \pagestyle{empty}
 \renewcommand*\familydefault{\sfdefault}
 

doc/dia/sample-instance-1.tex

 
 \tikzset{
     node distance = 1.5cm,
-    class/.style = {draw, rectangle split, rectangle split parts=2,
-                    text width=4cm, text centered}
+    entity/.style = {fill=black!10, circle,
+                     text width=1.5cm, minimum size=3cm,
+                     text centered, font=\small\ttfamily},
+    value/.style = {fill=black!10, rectangle,
+                    text width=1.5cm, minimum size=3cm,
+                    text centered, font=\small\ttfamily}
 }
 
 \begin{tikzpicture}
 
-\node[class] (school)
-    {school \nodepart{second} \texttt{[eng]}, \texttt{[la]}, \texttt{[ns]}, \ldots};
-\node[class] (boolean) [right=of school]
-    {boolean \nodepart{second} \texttt{false}, \texttt{true}};
-\node[class] (integer) [right=of boolean]
-    {integer \nodepart{second} \ldots, \texttt{-1}, \texttt{0}, \texttt{1}, \ldots};
+\node[entity, label=above:school] (school)
+    {$\vdots$ \\ {[eng]} \\ {[la]} \\ {[ns]} \\ $\vdots$};
+\node[value, label=above:boolean] (boolean) [right=of school]
+    {false \\ true};
+\node[value, label=above:integer] (school) [right=of boolean]
+    {$\vdots$ \\ -1 \\ 0 \\ 1 \\ $\vdots$};
 
 \end{tikzpicture}
 

doc/dia/sample-instance-2.tex

 \begin{document}
 
 \tikzset{
-    node distance = 0.5cm,
-    class/.style = {draw, rectangle split, rectangle split parts=2,
-                    text width=4cm, text centered}
+    > = stealth',
+    node distance = 0.5cm and 2.5cm,
+    unit/.style = {fill=black!10, star, star points=8,
+                   text width=1cm,
+                   text centered, font=\large\ttfamily},
+    entity/.style = {fill=black!10, circle,
+                     text width=1.5cm, minimum size=4cm,
+                     text centered, font=\small\ttfamily},
+    value/.style = {fill=black!10, rectangle,
+                    text width=5cm, minimum size=4cm,
+                    text centered, font=\small\ttfamily},
+    link/.style = {font=\ttfamily},
 }
 
 \begin{tikzpicture}
 
-\node[class] (department)
-    {department \nodepart{second} \texttt{[comp]}, \texttt{[ee]}, \ldots};
-\node[class] (school) [right=of department]
-    {school \nodepart{second} \texttt{[eng]}, \ldots};
-\node[class, text width=6cm] (string) [right=of school]
-    {string \nodepart{second} \ldots, \texttt{'School of Engineering'}, \ldots};
+\node[unit] (unit)
+    {{@}};
+\node[entity] (school) [right=of unit]
+    {$\vdots$ \\ {[eng]} \\ {[la]} \\ {[ns]} \\ $\vdots$};
+\node[entity] (department) [below=of school]
+    {$\vdots$ \\ {[chem]} \\ {[hist]} \\ {[psych]} \\
+     {[be]} \\ {[ee]} \\ {[me]} \\ $\vdots$};
+\node[value] (string) [left=of department]
+    {$\vdots$ \\ {'Chemistry'} \\ {'History'} \\ {'Psychology'} \\
+     {'Bioengineering'} \\ {'Electrical Engineering'} \\ {'Mechanical Engineering'} \\ $\vdots$};
 
-\coordinate (department/comp)
-    at ($ (department.south) +(-25pt,3pt) $);
-\coordinate (department/ee)
-    at ($ (department.south) +(10pt,3pt) $);
-\coordinate (school/eng/from/ee)
-    at ($ (school.south) +(-15pt,3pt) $);
-\coordinate (school/eng/from/comp)
-    at ($ (school.south) +(-10pt,3pt) $);
-\coordinate (school/eng/to/string)
-    at ($ (school.south) +(-5pt,3pt) $);
-\coordinate (string/eng)
-    at ($ (string.south) +(0pt,3pt) $);
+\coordinate (unit out)
+    at ($ (unit) +(5pt,0pt) $);
 
-\draw[->,bend right]
-    (department/comp) to (school/eng/from/comp);
-\draw[->,bend right]
-    (department/ee) to (school/eng/from/ee);
-\draw[->,bend right]
-    (school/eng/to/string) to (string/eng);
+\coordinate (eng in)
+    at ($ (school) +(-15pt,9pt) $);
+\coordinate (la in)
+    at ($ (school) +(-15pt,-2pt) $);
+\coordinate (ns in)
+    at ($ (school) +(-15pt,-13pt) $);
+\coordinate (eng out)
+    at ($ (school) +(15pt,9pt) $);
+\coordinate (la out)
+    at ($ (school) +(15pt,-2pt) $);
+\coordinate (ns out)
+    at ($ (school) +(15pt,-13pt) $);
+
+\coordinate (chem in)
+    at ($ (department) +(20pt,26pt) $);
+\coordinate (hist in)
+    at ($ (department) +(20pt,15pt) $);
+\coordinate (psych in)
+    at ($ (department) +(20pt,4pt) $);
+\coordinate (be in)
+    at ($ (department) +(15pt,-8pt) $);
+\coordinate (ee in)
+    at ($ (department) +(15pt,-19pt) $);
+\coordinate (me in)
+    at ($ (department) +(15pt,-30pt) $);
+\coordinate (chem out)
+    at ($ (department) +(-20pt,26pt) $);
+\coordinate (hist out)
+    at ($ (department) +(-20pt,15pt) $);
+\coordinate (psych out)
+    at ($ (department) +(-20pt,4pt) $);
+\coordinate (be out)
+    at ($ (department) +(-15pt,-8pt) $);
+\coordinate (ee out)
+    at ($ (department) +(-15pt,-19pt) $);
+\coordinate (me out)
+    at ($ (department) +(-15pt,-30pt) $);
+
+\coordinate (chem name)
+    at ($ (string) +(35pt,26pt) $);
+\coordinate (hist name)
+    at ($ (string) +(35pt,15pt) $);
+\coordinate (psych name)
+    at ($ (string) +(35pt,4pt) $);
+\coordinate (be name)
+    at ($ (string) +(50pt,-8pt) $);
+\coordinate (ee name)
+    at ($ (string) +(60pt,-19pt) $);
+\coordinate (me name)
+    at ($ (string) +(60pt,-30pt) $);
+
+\draw[->]
+    (unit out) to node[link, above=0.2cm] {school} (eng in);
+\draw[->]
+    (unit out) to (la in);
+\draw[->]
+    (unit out) to (ns in);
+
+\draw[->, bend left=60]
+    (eng out) to node[link, right=0.2cm] {department} (me in);
+\draw[->, bend left=60]
+    (eng out) to (ee in);
+\draw[->, bend left=60]
+    (eng out) to (be in);
+\draw[->, bend left=45]
+    (la out) to (hist in);
+\draw[->, bend left=45]
+    (la out) to (psych in);
+\draw[->, bend left=30]
+    (ns out) to (chem in);
+
+\draw[->]
+    (chem out) to node[link, above=0.2cm] {name} (chem name);
+\draw[->]
+    (hist out) to (hist name);
+\draw[->]
+    (psych out) to (psych name);
+\draw[->]
+    (be out) to (be name);
+\draw[->]
+    (ee out) to (ee name);
+\draw[->]
+    (me out) to (me name);
 
 \end{tikzpicture}
 

doc/dia/sample-model.tex

 \begin{document}
 
 \tikzset{
-    > = stealth', shorten > = 5pt, shorten < = 5pt,
-    node distance = .5cm and 2.5cm,
-    class/.style = {draw, rectangle,
-                    minimum width=2.5cm, minimum height=1cm,
-                    text height=1.5ex, text depth=.25ex},
-    link/.style = {font=\small\itshape}
+    > = stealth', shorten > = 1pt, shorten < = 1pt,
+    node distance = 3cm and 3cm,
+    unit/.style = {fill, star, star points=8, inner sep=0pt, minimum size=3mm},
+    entity/.style = {fill, circle, inner sep=0pt, minimum size=2mm},
+    value/.style = {fill, rectangle, inner sep=0pt, minimum size=2mm},
+    link/.style = {font=\small\ttfamily, above, sloped},
+    label/.style = {font=\small\color{black!70}},
+    information/.style = {rounded corners, inner sep=1ex, fill=blue!5}
 }
 
+\pgfdeclarelayer{background}
+\pgfsetlayers{background,main}
+
 \begin{tikzpicture}
 
-\node[class,ultra thick] (school)
-    {school};
-\node[class] (string) [right=of school]
-    {string};
-\node[class] (department) [above left=of school]
-    {department};
-\node[class] (program) [below left=of school]
-    {program};
+\node[unit] (unit) {};
+\node[entity] (school) [below right=3cm and 1.5cm of unit] {};
+\node[entity] (program) [right=of school] {};
+\node[entity] (department) [below left=3cm and 1.5cm of unit] {};
+\node[entity] (course) [left=of department] {};
+\node[value] (string) [below=of department] {};
 
-\draw[->,bend left]
-    (school)
-    to node[link,above] {code}
-    (string);
+\draw[->]
+    (unit)
+    to[bend left] node[link, near end] {program}
+    (program);
+\draw[->, very thick]
+    (unit)
+    to[bend left] node[link] {school}
+    (school);
+\draw[->]
+    (unit)
+    to[bend right] node[link] {department}
+    (department);
+\draw[->]
+    (unit)
+    to[bend right] node[link, near end] {course}
+    (course);
+
+\draw[->]
+    (program)
+    to[bend right] node[link] {school}
+    (school);
 \draw[->]
     (school)
-    to node[link,above] {name}
+    to[bend right] node[link] {program}
+    (program);
+\draw[->, very thick]
+    (school)
+    to[bend right] node[link] {department}
+    (department);
+\draw[->]
+    (department)
+    to[bend right] node[link] {school}
+    (school);
+\draw[->]
+    (department)
+    to[bend right] node[link] {course}
+    (course);
+\draw[->]
+    (course)
+    to[bend right] node[link] {department}
+    (department);
+\draw[->]
+    (program)
+    edge[loop, min distance=2cm, in=-35, out=35] node[link] {part\_of}
+    (program);
+\draw[<-]
+    (program)
+    edge[loop, min distance=6cm, in=-60, out=60] node[link] {program\_via\_part\_of}
+    (program);
+
+\draw[->]
+    (department)
+    to[bend left] node[link] {code}
     (string);
-\draw[->,bend right]
-    (school)
-    to node[link,above] {campus}
+\draw[->, very thick]
+    (department)
+    to node[link] {name}
     (string);
 \draw[->]
     (department)
-    to node[link,sloped,above] {school}
-    (school);
-\draw[->]
-    (program)
-    to node[link,sloped,above] {school}
-    (school);
+    to[bend right] node[link, below, rotate=180] {school\_code}
+    (string);
+
+\node[unit] (unit info) [below=2 of school] {};
+\node[entity] (entity info) [below=1ex of unit info] {};
+\node[value] (value info) [below=1ex of entity info] {};
+\node[label] (unit label) [right=.5em of unit info]
+    {unit class};
+\node[label] (entity label) [right=.5em of entity info]
+    {entity class};
+\node[label] (value label) [right=.5em of value info]
+    {value class};
+
+\begin{pgfonlayer}{background}
+    \node[information]
+        [fit=(unit info) (entity info) (value info)
+             (unit label) (entity label) (value label)] {};
+\end{pgfonlayer}
 
 \end{tikzpicture}
 

doc/dia/singular-links.tex

 \begin{document}
 
 \tikzset{
-    > = stealth', shorten > = 1pt, shorten < = 1pt,
-    node distance = 2.5cm and .5cm,
-    class/.style = {draw, rectangle},
-    item/.style = {fill, circle},
-    header/.style = {font=\bfseries},
+    > = stealth',
+    node distance = 0.5cm and 2cm,
+    entity/.style = {fill=black!10, circle,
+                     text width=1.5cm, minimum size=4cm,
+                     text centered, font=\small\ttfamily},
+    value/.style = {fill=black!10, rectangle,
+                    text width=4cm, minimum size=4cm,
+                    text centered, font=\small\ttfamily},
+    link/.style = {font=\ttfamily, above},
+    brace/.style = {decorate, decoration={brace,amplitude=8pt,raise=4pt},
+                    draw=blue!50},
+    brace header/.style = {below=10pt, font=\itshape\color{blue!75}}
 }
 
 \begin{tikzpicture}
 
-\node[item] (a1) {};
-\node[item] (a2) [right=of a1] {};
-\node[item] (a3) [right=of a2] {};
-\node[item] (a4) [right=of a3] {};
-\node[item] (a5) [right=of a4] {};
+\node[entity, label=above:school] (school)
+    {$\vdots$ \\ {[eng]} \\ {[la]} \\ {[ns]} \\ $\vdots$};
+\node[entity, label=above:department] (department) [right=of school]
+    {$\vdots$ \\ {[be]} \\ {[ee]} \\ {[me]} \\
+     {[hist]} \\ {[psych]} \\ {[chem]} \\ $\vdots$};
+\node[value, label=above:string] (string) [left=of school]
+    {$\vdots$ \\ {'north'} \\ {'old'} \\ {'south'} \\ $\vdots$};
 
-\node[item] (b1) [below=of a1] {};
-\node[item] (b2) [right=of b1] {};
-\node[item] (b3) [right=of b2] {};
-\node[item] (b4) [right=of b3] {};
-\node[item] (b5) [right=of b4] {};
+\coordinate (eng 1 out)
+    at ($ (school) +(15pt,9pt) $);
+\coordinate (la 1 out)
+    at ($ (school) +(15pt,-2pt) $);
+\coordinate (ns 1 out)
+    at ($ (school) +(15pt,-13pt) $);
+\coordinate (eng 2 out)
+    at ($ (school) +(-15pt,9pt) $);
+\coordinate (la 2 out)
+    at ($ (school) +(-15pt,-2pt) $);
+\coordinate (ns 2 out)
+    at ($ (school) +(-15pt,-13pt) $);
 
-\node[item] (c1) [right=2.5 of a5] {};
-\node[item] (c2) [right=of c1] {};
-\node[item] (c3) [right=of c2] {};
-\node[item] (c4) [right=of c3] {};
-\node[item] (c5) [right=of c4] {};
 
-\node[item] (d1) [below=of c1] {};
-\node[item] (d2) [right=of d1] {};
-\node[item] (d3) [right=of d2] {};
-\node[item] (d4) [right=of d3] {};
-\node[item] (d5) [right=of d4] {};
+\coordinate (be in)
+    at ($ (department) +(-15pt,26pt) $);
+\coordinate (ee in)
+    at ($ (department) +(-15pt,15pt) $);
+\coordinate (me in)
+    at ($ (department) +(-15pt,4pt) $);
+\coordinate (hist in)
+    at ($ (department) +(-20pt,-8pt) $);
+\coordinate (psych in)
+    at ($ (department) +(-20pt,-19pt) $);
+\coordinate (chem in)
+    at ($ (department) +(-20pt,-30pt) $);
 
-\node[class] (A) [fit=(a1) (a2) (a3) (a4) (a5)] {};
-\node[class] (B) [fit=(b1) (b2) (b3) (b4) (b5)] {};
-\node[class] (C) [fit=(c1) (c2) (c3) (c4) (c5)] {};
-\node[class] (D) [fit=(d1) (d2) (d3) (d4) (d5)] {};
+\coordinate (north in)
+    at ($ (string) +(20pt,9pt) $);
+\coordinate (old in)
+    at ($ (string) +(20pt,-2pt) $);
+\coordinate (south in)
+    at ($ (string) +(20pt,-13pt) $);
 
-\node[header] at (A.north) [above]
-    {Singular};
-\node[header] at (C.north) [above]
-    {Plural};
+\draw[->]
+    (eng 1 out) to node[link, above=0.5cm] {department} (be in);
+\draw[->]
+    (eng 1 out) to (ee in);
+\draw[->]
+    (eng 1 out) to (me in);
+\draw[->]
+    (la 1 out) to (hist in);
+\draw[->]
+    (la 1 out) to (psych in);
+\draw[->]
+    (ns 1 out) to (chem in);
 
-\draw[->] (a1) to (b2);
-\draw[->] (a2) to (b3);
-\draw[->] (a3) to (b3);
-\draw[->] (a5) to (b4);
+\draw[->]
+    (eng 2 out) to node[link, above=0.5cm] {campus} (north in);
+\draw[->]
+    (la 2 out) to (old in);
+\draw[->]
+    (ns 2 out) to (old in);
 
-\draw[->] (c1) to (d2);
-\draw[->] (c2) to (d2);
-\draw[->] (c2) to (d3);
-\draw[->] (c3) to (d3);
-\draw[->] (c5) to (d4);
-\draw[->] (c5) to (d5);
+\draw[brace]
+    ($ (department.south) -(5pt,0) $)
+    -- node[brace header] {a plural link}
+    ($ (school.south) +(5pt,0) $);
+\draw[brace]
+    ($ (school.south) -(5pt,0) $)
+    -- node[brace header] {a singular link}
+    ($ (string.south) +(5pt,0) $);
 
 \end{tikzpicture}
 

doc/dia/total-links.tex

 \begin{document}
 
 \tikzset{
-    > = stealth', shorten > = 1pt, shorten < = 1pt,
-    node distance = 2.5cm and .5cm,
-    class/.style = {draw, rectangle},
-    item/.style = {fill, circle},
-    header/.style = {font=\bfseries},
+    > = stealth',
+    node distance = 0.5cm and 2cm,
+    entity/.style = {fill=black!10, circle,
+                     text width=2cm, minimum size=4cm,
+                     text centered, font=\small\ttfamily},
+    value/.style = {fill=black!10, rectangle,
+                    text width=4cm, minimum size=4cm,
+                    text centered, font=\small\ttfamily},
+    link/.style = {font=\ttfamily, above},
+    brace/.style = {decorate, decoration={brace,amplitude=8pt,raise=4pt},
+                    draw=blue!50},
+    brace header/.style = {below=10pt, font=\itshape\color{blue!75}}
 }
 
 \begin{tikzpicture}
 
-\node[item] (a1) {};
-\node[item] (a2) [right=of a1] {};
-\node[item] (a3) [right=of a2] {};
-\node[item] (a4) [right=of a3] {};
-\node[item] (a5) [right=of a4] {};
+\node[entity, label=above:school] (school)
+    {$\vdots$ \\ {[eng]} \\ {[la]} \\ {[ns]} \\ $\vdots$};
+\node[entity, label=above:program] (program) [right=of school]
+    {$\vdots$ \\ {[eng.gee]} \\ {[eng.uelec]} \\ {[la.uhist]} \\
+     {[ns.pmth]} \\ {[ns.gmth]} \\ {[ns.umth]} \\ $\vdots$};
 
-\node[item] (b1) [below=of a1] {};
-\node[item] (b2) [right=of b1] {};
-\node[item] (b3) [right=of b2] {};
-\node[item] (b4) [right=of b3] {};
-\node[item] (b5) [right=of b4] {};
+\coordinate (eng in)
+    at ($ (school) +(15pt,9pt) $);
+\coordinate (la in)
+    at ($ (school) +(15pt,-2pt) $);
+\coordinate (ns in)
+    at ($ (school) +(15pt,-13pt) $);
 
-\node[item] (c1) [right=2.5 of a5] {};
-\node[item] (c2) [right=of c1] {};
-\node[item] (c3) [right=of c2] {};
-\node[item] (c4) [right=of c3] {};
-\node[item] (c5) [right=of c4] {};
+\coordinate (gee 1 out)
+    at ($ (program) +(-30pt,26pt) $);
+\coordinate (uelec 1 out)
+    at ($ (program) +(-30pt,15pt) $);
+\coordinate (uhist 1 out)
+    at ($ (program) +(-30pt,4pt) $);
+\coordinate (pmth 1 out)
+    at ($ (program) +(-25pt,-8pt) $);
+\coordinate (gmth 1 out)
+    at ($ (program) +(-25pt,-19pt) $);
+\coordinate (umth 1 out)
+    at ($ (program) +(-25pt,-30pt) $);
+\coordinate (gee 2 out)
+    at ($ (program) +(30pt,26pt) $);
+\coordinate (uelec 2 out)
+    at ($ (program) +(30pt,15pt) $);
+\coordinate (uhist 2 out)
+    at ($ (program) +(30pt,4pt) $);
+\coordinate (pmth 2 out)
+    at ($ (program) +(25pt,-8pt) $);
+\coordinate (gmth 2 out)
+    at ($ (program) +(25pt,-19pt) $);
+\coordinate (umth 2 out)
+    at ($ (program) +(25pt,-30pt) $);
 
-\node[item] (d1) [below=of c1] {};
-\node[item] (d2) [right=of d1] {};
-\node[item] (d3) [right=of d2] {};
-\node[item] (d4) [right=of d3] {};
-\node[item] (d5) [right=of d4] {};
+\draw[->]
+    (gee 1 out) to node[link, above=0.5cm] {school} (eng in);
+\draw[->]
+    (uelec 1 out) to (eng in);
+\draw[->]
+    (uhist 1 out) to (la in);
+\draw[->]
+    (pmth 1 out) to (ns in);
+\draw[->]
+    (gmth 1 out) to (ns in);
+\draw[->]
+    (umth 1 out) to (ns in);
 
-\node[class] (A) [fit=(a1) (a2) (a3) (a4) (a5)] {};
-\node[class] (B) [fit=(b1) (b2) (b3) (b4) (b5)] {};
-\node[class] (C) [fit=(c1) (c2) (c3) (c4) (c5)] {};
-\node[class] (D) [fit=(d1) (d2) (d3) (d4) (d5)] {};
+\draw[->, bend right=90, looseness=15]
+    (uelec 2 out) to (gee 2 out);
+\draw[->, bend right=90, looseness=15]
+    (gmth 2 out) to (pmth 2 out);
+\draw[->, bend right=90, looseness=15]
+    (umth 2 out) to (gmth 2 out);
 
-\node[header] at (A.north) [above]
-    {Total};
-\node[header] at (C.north) [above]
-    {Partial};
-
-\draw[->] (a1) to (b2);
-\draw[->] (a2) to (b2);
-\draw[->] (a3) to (b2);
-\draw[->] (a3) to (b4);
-\draw[->] (a4) to (b3);
-\draw[->] (a4) to (b5);
-\draw[->] (a5) to (b5);
-
-\draw[->] (c1) to (d2);
-\draw[->] (c3) to (d2);
-\draw[->] (c3) to (d4);
-\draw[->] (c4) to (d3);
-\draw[->] (c4) to (d5);
+\draw[brace]
+    ($ (program.south) -(5pt,0) $)
+    -- node[brace header] {a total link}
+    ($ (school.south) +(5pt,0) $);
+\draw[brace]
+    ($ (program.north east) +(35pt,0) $)
+    -- node[brace header, sloped, above=10pt] {a partial link}
+    ($ (program.south east) +(35pt,0) $);
 
 \end{tikzpicture}
 

doc/dia/unique-links.tex

 \begin{document}
 
 \tikzset{
-    > = stealth', shorten > = 1pt, shorten < = 1pt,
-    node distance = 2.5cm and .5cm,
-    class/.style = {draw, rectangle},
-    item/.style = {fill, circle},
-    header/.style = {font=\bfseries},
+    > = stealth',
+    node distance = 0.5cm and 2cm,
+    entity/.style = {fill=black!10, circle,
+                     text width=1.5cm, minimum size=4cm,
+                     text centered, font=\small\ttfamily},
+    value/.style = {fill=black!10, rectangle,
+                    text width=4.5cm, minimum size=4cm,
+                    text centered, font=\small\ttfamily},
+    link/.style = {font=\ttfamily, above},
+    brace/.style = {decorate, decoration={brace,amplitude=8pt,raise=4pt},
+                    draw=blue!50},
+    brace header/.style = {below=10pt, font=\itshape\color{blue!75}}
 }
 
 \begin{tikzpicture}
 
-\node[item] (a1) {};
-\node[item] (a2) [right=of a1] {};
-\node[item] (a3) [right=of a2] {};
-\node[item] (a4) [right=of a3] {};
-\node[item] (a5) [right=of a4] {};
+\node[entity, label=above:school] (school)
+    {$\vdots$ \\ {[eng]} \\ {[la]} \\ {[ns]} \\ $\vdots$};
+\node[entity, label=above:department] (department) [left=of school]
+    {$\vdots$ \\ {[be]} \\ {[ee]} \\ {[me]} \\
+     {[hist]} \\ {[psych]} \\ {[chem]} \\ $\vdots$};
+\node[value, label=above:name] (name) [left=of department]
+    {$\vdots$ \\
+     {'Bioengineering'} \\ {'Electrical Engineering'} \\ {'Mechanical Engineering'} \\
+     {'History'} \\ {'Psychology'} \\ {'Chemistry'} \\ $\vdots$};
 
-\node[item] (b1) [below=of a1] {};
-\node[item] (b2) [right=of b1] {};
-\node[item] (b3) [right=of b2] {};
-\node[item] (b4) [right=of b3] {};
-\node[item] (b5) [right=of b4] {};
+\coordinate (eng in)
+    at ($ (school) +(-15pt,9pt) $);
+\coordinate (la in)
+    at ($ (school) +(-15pt,-2pt) $);
+\coordinate (ns in)
+    at ($ (school) +(-15pt,-13pt) $);
 
-\node[item] (c1) [right=2.5 of a5] {};
-\node[item] (c2) [right=of c1] {};
-\node[item] (c3) [right=of c2] {};
-\node[item] (c4) [right=of c3] {};
-\node[item] (c5) [right=of c4] {};
+\coordinate (be 1 out)
+    at ($ (department) +(15pt,26pt) $);
+\coordinate (ee 1 out)
+    at ($ (department) +(15pt,15pt) $);
+\coordinate (me 1 out)
+    at ($ (department) +(15pt,4pt) $);
+\coordinate (hist 1 out)
+    at ($ (department) +(20pt,-8pt) $);
+\coordinate (psych 1 out)
+    at ($ (department) +(20pt,-19pt) $);
+\coordinate (chem 1 out)
+    at ($ (department) +(20pt,-30pt) $);
+\coordinate (be 2 out)
+    at ($ (department) +(-15pt,26pt) $);
+\coordinate (ee 2 out)
+    at ($ (department) +(-15pt,15pt) $);
+\coordinate (me 2 out)
+    at ($ (department) +(-15pt,4pt) $);
+\coordinate (hist 2 out)
+    at ($ (department) +(-20pt,-8pt) $);
+\coordinate (psych 2 out)
+    at ($ (department) +(-20pt,-19pt) $);
+\coordinate (chem 2 out)
+    at ($ (department) +(-20pt,-30pt) $);
 
-\node[item] (d1) [below=of c1] {};
-\node[item] (d2) [right=of d1] {};
-\node[item] (d3) [right=of d2] {};
-\node[item] (d4) [right=of d3] {};
-\node[item] (d5) [right=of d4] {};
+\coordinate (be name)
+    at ($ (name) +(50pt,26pt) $);
+\coordinate (ee name)
+    at ($ (name) +(60pt,15pt) $);
+\coordinate (me name)
+    at ($ (name) +(60pt,4pt) $);
+\coordinate (hist name)
+    at ($ (name) +(35pt,-8pt) $);
+\coordinate (psych name)
+    at ($ (name) +(35pt,-19pt) $);
+\coordinate (chem name)
+    at ($ (name) +(35pt,-30pt) $);
 
-\node[class] (A) [fit=(a1) (a2) (a3) (a4) (a5)] {};
-\node[class] (B) [fit=(b1) (b2) (b3) (b4) (b5)] {};
-\node[class] (C) [fit=(c1) (c2) (c3) (c4) (c5)] {};
-\node[class] (D) [fit=(d1) (d2) (d3) (d4) (d5)] {};
+\draw[->]
+    (be 1 out) to (eng in);
+\draw[->]
+    (ee 1 out) to (eng in);
+\draw[->]
+    (me 1 out) to (eng in);
+\draw[->]
+    (hist 1 out) to (la in);
+\draw[->]
+    (psych 1 out) to (la in);
+\draw[->]
+    (chem 1 out) to (ns in);
 
-\node[header] at (A.north) [above]
-    {Unique};
-\node[header] at (C.north) [above]
-    {Non-unique};
+\draw[->]
+    (be 2 out) to (be name);
+\draw[->]
+    (ee 2 out) to (ee name);
+\draw[->]
+    (me 2 out) to (me name);
+\draw[->]
+    (hist 2 out) to (hist name);
+\draw[->]
+    (psych 2 out) to (psych name);
+\draw[->]
+    (chem 2 out) to (chem name);
 
-\draw[->] (a1) to (b2);
-\draw[->] (a2) to (b3);
-\draw[->] (a3) to (b5);
-\draw[->] (a5) to (b1);
-\draw[->] (a5) to (b4);
-
-\draw[->] (c1) to (d2);
-\draw[->] (c2) to (d3);
-\draw[->] (c3) to (d5);
-\draw[->] (c5) to (d2);
-\draw[->] (c5) to (d5);
+\draw[brace]
+    ($ (school.south) -(5pt,0) $)
+    -- node[brace header] {a non-unique link}
+    ($ (department.south) +(5pt,0) $);
+\draw[brace]
+    ($ (department.south) -(5pt,0) $)
+    -- node[brace header] {a unique link}
+    ($ (name.south) +(5pt,0) $);
 
 \end{tikzpicture}
 

doc/ref/model.rst

    :local:
 
 HTSQL is not a full-fledged database system.  As opposed to regular data
-stores, it does not include a storage layer, but relies on a relational
+stores, it does not include a storage layer, but relies on a SQL
 database server to physically store and retrieve data.
 
 HTSQL is designed to work on top of existing relational databases and
 relational model directly to the users.  Instead it derives *HTSQL data
 model* from the underlying database and uses this model when presenting
 data to the users and interpreting user queries.  HTSQL data model is
-very close to traditional `network data model`_ utilized by CODASYL, and
+very close to traditional `network data model`_ utilized by CODASYL and
 various OODBMS and ORM systems.
 
 .. _network data model: http://en.wikipedia.org/wiki/Network_model
 university.  This model may contain schools, programs administered
 by a school, departments associated with a school, and courses offered
 by a department.  A concrete instance of this model may contain
-a school of *Engineering* with associated departments of *Computer
-Science*, *Electrical Engineering*, etc.:
+a school of *Engineering* with an associated department of *Computer
+Science*, which offers a *Database Theory* course, etc.:
 
 .. diagram:: ../dia/model-and-instance.tex
    :align: center
 Classes and Links
 =================
 
-HTSQL structures the data with *classes* and *links*, which together
-form *a model graph*.  Classes, which are the nodes in the model graph,
-represents types of entities.  Links, which are the arcs in the model
-graph, describe relations between entities.  Both classes and links
-have a name.
+HTSQL represents a database model in form of a directed graph; the nodes
+of the graph are called *classes* and the arcs are called *links*.
 
-Among classes we distinguish *domain classes* and *record classes*.
-Domain classes represent scalar data types such as `boolean`, `integer`,
-`string`, `date`.  Record classes represent types of business entities
-modeled by the database.  A student enrollment system in our example
-would have record classes such as `school`, `program`, `department`,
-`course`.
+We distinguish several types of classes:
 
-Links are classified by the type of classes they connect.  A link from a
-record class to a domain class indicates that records of this class have
-an attribute, which type is specified by the domain class.  For example,
-`school` class may have a link called `name` to `string` class, which
-indicates that each *school* record has a string attribute *name*.
+* A *value class* represents a scalar data type such as `boolean`,
+  `integer`, `string`, `date`.
+* An *entity class* represents a collection of homogeneous entities
+  modeled by the database.  For instance, a student enrollment database
+  may contain entity classes such as `school`, `program`, `department`,
+  `course`.
+* Each database model contains one instance of a *unit class*.  It
+  serves as an origin node when we construct paths in the model graph.
 
-A link between two record classes indicates that records of these
-classes are related to each other.  For example, `department` class
-has a link to `school` class, which indicates that each *department*
-record may be associated with some *school* record.
+A link represents a relationship between two classes.
+
+* Each entity class has a link from the unit class.  This link
+  represents the set of all entities from the class.
+* A link connecting an entity class to a value class represents an
+  entity attribute.
+* A link between two entity classes denotes a relation between the
+  respective entities.
+
+Each link has a name, which must be unique among all links sharing the
+same origin class.  We use a dot-separated sequence of link names to
+identify a path in the model graph that starts at the unit class.
+Thus ``school.department.name`` identifies a path with three links:
+``school`` connecting the unit class to an entity class, ``department``
+connecting two entity classes and ``name`` connecting an entity class to
+a value class.
+
+We will routinely use the dotted notation to refer to the last link or
+the target class in the path.  For example, we write ``school`` to
+indicate the `school` class, ``department.name`` to indicate link
+``name`` from `department` class to `string` class.
+
+The following diagram shows a fragment of the model graph for our
+student enrollment database (most of the value classes and attribute
+links are omitted for clarity).
 
 .. diagram:: ../dia/sample-model.tex
    :align: center
 
-Since different links may have the same name, we will use dotted
-notation `class.link` to indicate links.  Here, `class` is the name of a
-class, `link` is the name of a link originating from the class.  Thus,
-`school.name` and `department.school` are links on the diagram.
+The marked path on the diagram represents the query:
 
+.. htsql:: /school.department.name
+   :cut: 3
 
-Records and Relations
-=====================
+
+Entities and Relations
+======================
 
 As we focus from the database model to a specific instance, classes
-are populated with values and records, and links are expanded to
-relations between individual items.
+are populated with values and entities, and each link splits into
+connections between individual class elements.
 
-On the instance level, a domain class is transformed into a set of all
-values of the respective type.  Thus, `boolean` class contains two
-values: ``true`` and ``false``, `integer` class contains all integer
-numbers, and so on.
+A value class is populated with all values of the respective type.
+Thus, `boolean` class acquires two values: ``true`` and ``false``,
+`integer` class is filled with all integer numbers, and so on.
 
-A record class becomes a set of records representing business entities
-of this class.
+An entity class becomes a set of homogeneous business entities; e.g.
+`school` class becomes a set of university schools, `department` a set
+of departments, etc.
 
-It is convenient to depict an entity as a collection of attribute
-values, hence the word "record".  Even though it is permitted for two
-different records to have the same set of attribute values, in practice,
-there often exists an attribute or a group of attributes which could
-uniquely identify a record.  We use the value of such an attribute
-enclosed in brackets to denote records in writing.  Thus, an instance of
-class `school` may contain records ``[eng]``, ``[la]``, ``[ns]``
-representing respectively schools of *Engineering*, of *Arts and
-Humanities*, and of *Natural Sciences*, assuming that we use attribute
-`school.code` to uniquely identify records.
+In HTSQL, individual entities are not observable, only entity attributes
+are.  When we need to refer to a specific entity in writing, we use the
+value of some entity attribute that can uniquely identify it, enclosed
+in brackets.  For example, attribute `school.code` uniquely identifies
+`school` entities, therefore we may say that ``[eng]``, ``[la]``,
+``[ns]`` are respectively entities representing schools of
+*Engineering*, of *Arts and Humanities*, and of *Natural Sciences*.
+
+The unit class contains a single value, which is called *unit*
+and denoted by ``@``.
 
 .. diagram:: ../dia/sample-instance-1.tex
    :align: center
 
-A link between two classes is unwound into connections between elements
-of these classes.  If in the database model a link represents an entity
-attribute, in a specific instance a link connects records to attribute
-values.  A link between two record classes would connect records of
-these classes.
+A link between two classes splits into a binary relation between
+elements of these classes:
 
-For example, link `school.name` connects a school record ``[eng]`` to a
-string value ``'School of Engineering'``.  The record ``[eng]`` is also
-connected to department records ``[comp]`` and ``[ee]`` indicating that
-*Department of Computer Science* and *Department of Electrical
-Engineering* belong to *School of Engineering*.
+* A link from the unit class to an entity class connects the unit
+  to every entity in the entity class.
+* A link between two entity classes connects each entity of the
+  origin class to all related entities from the target class.
+* A link from an entity class to a value class connects each
+  entity with the respective attribute value.
+
+The following diagram demonstrates how the path
+``school.department.name`` looks for some specific database instance.
 
 .. diagram:: ../dia/sample-instance-2.tex
    :align: center
 
-Some links may enforce constraints on connections between elements.
-We classify these constraints as follows:
+
+Link Constraints
+================
+
+Links may enforce constraints on connections between elements.  We
+recognize the following constraints: singularity, totality and
+uniqueness.
+
+Note that links constraints are defined on the database model
+and applied to all instances of the model.
+
+Singular and Plural Links
+-------------------------
 
 A link is called *singular* if any element of the origin class is
 connected to no more than one element of the target class.  Otherwise,
 the link is called *plural*.
 
-For example, all links representing attributes are singular; link
-`department.school` is also singular because each department may be
-associated with just one school, but the *reverse* link
-`school.department` is plural since a school may contain more than one
-department.
+* All attribute links are singular.
+* Any link from the unit class to an entity class is plural.
+* A link between two entity classes may be singular or plural.  For
+  example, link ``department.school`` is singular because each
+  department may be associated with just one school, but the *reverse*
+  link ``school.department`` is plural since a school may include more
+  than one department.
+
+The following diagram visualises a singular link ``school.campus`` and
+a plural link ``school.department``.
 
 .. diagram:: ../dia/singular-links.tex
    :align: center
 
-A link is called *total* if any element of the origin class is connected
-to at least one element of the target class.  Otherwise, the link is
-called *partial*.
+Total and Partial Links
+-----------------------
 
-For example, we require that every school entity has a code, therefore
-attribute `school.code` is total.  We also permit a department
-to lack an associated school, which means link `department.school`
-is partial.
+A link is called *total* if each element of the origin class is
+connected to at least one element of the target class.  Otherwise, the
+link is called *partial*.
+
+For example, we require every program to be associated with some school,
+so link `program.school` is total.  At the same time, not every program
+is a part of another program, therefore link `program.part_of` is
+partial.
 
 .. diagram:: ../dia/total-links.tex
    :align: center
 
+Unique and Non-unique Links
+---------------------------
+
 A link is called *unique* if any element of the target class is
 connected to no more than one element of the origin class.  Otherwise,
 the link is *non-unique*.
 
-Attribute `school.name` is unique since different school entities must
-have different names, but link `department.school` is non-unique as
-different departments are allowed to be associated with the same school.
+Attribute `department.name` is unique since different department
+entities must have different names, but link `department.school` is
+non-unique as different departments are allowed to be associated with
+the same school.
 
 .. diagram:: ../dia/unique-links.tex
    :align: center
 
-Note that links constraints are defined on the database model
-and applied to all instances of the model.
-
 
 Correspondence to the Relational Model
 ======================================
 In this section, we explain how underlying relation database model
 is translated to HTSQL data model.
 
-For the most part, translation of relational structure to HTSQL model
-is straightforward.  SQL data types become domain classes, SQL tables
-become record classes, table columns are class attributes.
+For the most part, translation of relational structure to HTSQL model is
+straightforward.  SQL data types become value classes, SQL tables become
+entity classes, table columns become class attributes.  Links between
+entity classes are inferred from FOREIGN KEY constraints.
+
+HTSQL allows the administrator to restrict access to specific tables and
+columns, configure additional database constraints, and rename link
+names.  In the following sections we describe how HTSQL describes
+database model in the absence of any configuration.
+
+A name in HTSQL is a sequence of letters, digits and ``_`` characters
+which doesn't start with a digit.  When an HTSQL name is generated from
+a SQL name which contains non-alphanumeric characters, those are
+replaced with an underscore (``_``).
+
+Entity Names
+------------
+
+Each SQL table induces an entity class, which, in general, borrows its
+name from the table.
+
+Some SQL database servers support a notion of *schemas*, namespaces for
+tables, which may cause a naming conflict when two or more different
+schemas have tables with the same name.  This conflict is resolved as
+follows:
+
+* If one of the schemas is marked as "default" for the purposes of name
+  resolution, the name of the respective table is borrowed unadorned.
+* For the remaining tables, the assigned name has the form
+  ``<schema>_<name>``.
+
+Attribute Names
+---------------
+
+Each table column induces an entity attribute with the same name.
+
+When the column is a ``FOREIGN KEY`` constraint, the column name is also
+used to refer to the respective entity link.  The usage is determined
+from the context; compare
+
+.. htsql:: /department.school_code
+   :cut: 3
+
+and
+
+.. htsql:: /department.school_code.*
+   :cut: 3
+
+Entity Links
+------------
+
+Each ``FOREIGN KEY`` constraint generates two links between respective
+entity classes, one in the direction of the constraint, called
+*direct*, and the other in the opposite direction, called *reverse*.
+
+The names of the links are synthesized from the names of the tables and
+names of the columns which form the constraint.  If the name of the
+referring column ends with the name of the referred column (e.g.
+``department.school_code`` and ``school.code``), we call the beginning
+of the referring column a *prefix* (in this case, ``school``).
+
+The link names are generated according to the following rules.  The
+adopted name is the first one which doesn't conflict with other link
+names with the same origin class.
+
+1. When the link is direct and the prefix exists, use the prefix.
+2. Use the name of the target table.  In case there are more than one
+   link to the same target, prefer the one for which the referring
+   column is a primary key.
+3. If the link is reverse and the prefix exists, use the name of the
+   form ``<target>_via_<prefix>``.
+4. If the link is reverse, use the name of the form
+   ``<target>_via_<column>``.
+
+Link Constraints
+----------------
 
 Column constraints are trivially translated to properties of the
-respective attributes.  ``NOT NULL`` constraint on a table column means,
-in HTSQL terms, that the respective class attribute is total.
-``UNIQUE`` constraint on a column indicates that the respective
-attribute link is unique.  ``PRIMARY KEY`` constraint indicates that the
-attribute link is both total and unique.
+respective attribute links.
 
-The link structure of the model graph is provided by foreign key
-constraints.  Specifically, a foreign key creates a singular link
-from the referring class to the referred class.
+* A ``NOT NULL`` constraint on a column means, in HTSQL term, that the
+  respective attribute is total.
+* A ``UNIQUE`` constraint indicates that the attribute is unique.
+* A ``PRIMARY KEY`` constraint indicates that the attribute is both
+  total and unique.  The columns that form a primary key are also used
+  for default ordering on the entity class.
+* A direct link induced by a ``FOREIGN KEY`` constraint is always
+  singular.  The reverse link is plural in general, but could be
+  singular when the key column is ``UNIQUE``.
+
+An Example
+----------
 
 Consider, for example, the following fragment of an SQL schema:
 
 .. sourcecode:: sql
 
-   CREATE TABLE ad.school (
-       code                VARCHAR(16) NOT NULL,
-       name                VARCHAR(64) NOT NULL,
-       campus              VARCHAR(5),
-       CONSTRAINT school_pk
-         PRIMARY KEY (code),
-       CONSTRAINT name_uk
-         UNIQUE (name),
-       CONSTRAINT school_campus_ck
-         CHECK (campus IN ('old', 'north', 'south'))
-   );
+    CREATE SCHEMA ad;
 
-   CREATE TABLE ad.department (
-       code                VARCHAR(16) NOT NULL,
-       name                VARCHAR(64) NOT NULL,
-       school_code         VARCHAR(16),
-       CONSTRAINT department_pk
-         PRIMARY KEY (code),
-       CONSTRAINT department_name_uk
-         UNIQUE (name),
-       CONSTRAINT department_school_fk
-         FOREIGN KEY (school_code)
-         REFERENCES ad.school(code)
-   );
+    CREATE TABLE ad.school (
+        code                VARCHAR(16) NOT NULL,
+        name                VARCHAR(64) NOT NULL,
+        campus              VARCHAR(5),
+        CONSTRAINT school_pk
+          PRIMARY KEY (code),
+        CONSTRAINT school_name_uk
+          UNIQUE (name),
+        CONSTRAINT school_campus_ck
+          CHECK (campus IN ('old', 'north', 'south'))
+    );
 
-HTSQL model of this schema consists of two classes, `school` and
-`department`, each with three attributes: `code`, `name`, `campus`
-and `code`, `name`, `school_code` respectively.  Additionally,
-the foreign key constraint ``department_school_fk`` generates
-a singular link from class `department` to class `school` and a
-reverse plural link from class `school` to class `department`.
+    CREATE TABLE ad.department (
+        code                VARCHAR(16) NOT NULL,
+        name                VARCHAR(64) NOT NULL,
+        school_code         VARCHAR(16),
+        CONSTRAINT department_pk
+          PRIMARY KEY (code),
+        CONSTRAINT department_name_uk
+          UNIQUE (name),
+        CONSTRAINT department_school_fk
+          FOREIGN KEY (school_code)
+          REFERENCES ad.school(code)
+    );
+
+    CREATE TABLE ad.program (
+        school_code         VARCHAR(16) NOT NULL,
+        code                VARCHAR(16) NOT NULL,
+        title               VARCHAR(64) NOT NULL,
+        degree              CHAR(2),
+        part_of_code        VARCHAR(16),
+        CONSTRAINT program_pk
+          PRIMARY KEY (school_code, code),
+        CONSTRAINT program_title_uk
+          UNIQUE (title),
+        CONSTRAINT program_degree_ck
+          CHECK (degree IN ('bs', 'pb', 'ma', 'ba', 'ct', 'ms', 'ph')),
+        CONSTRAINT program_school_fk
+          FOREIGN KEY (school_code)
+          REFERENCES ad.school(code),
+       CONSTRAINT program_part_of_fk
+          FOREIGN KEY (school_code, part_of_code)
+          REFERENCES ad.program(school_code, code)
+    );
+
+    CREATE TABLE ad.course (
+        department_code     VARCHAR(16) NOT NULL,
+        no                  INTEGER NOT NULL,
+        title               VARCHAR(64) NOT NULL,
+        credits             INTEGER,
+        description         TEXT,
+        CONSTRAINT course_pk
+          PRIMARY KEY (department_code, no),
+        CONSTRAINT course_title_uk
+          UNIQUE (title),
+        CONSTRAINT course_dept_fk
+          FOREIGN KEY (department_code)
+          REFERENCES ad.department(code)
+    );
+
+In this schema, four tables ``ad.school``, ``ad.department``,
+``ad.program``, ``ad.course`` generate four entity classes:
+
+.. htsql:: /school
+   :cut: 3
+
+.. htsql:: /department
+   :cut: 3
+
+.. htsql:: /program
+   :cut: 3
+
+.. htsql:: /course
+   :cut: 3
+
+Foreign key constraints ``department_school_fk``, ``program_school_fk``,
+``course_dept_fk`` generate three direct and three reverse links:
+
+.. htsql:: /department.school
+   :hide:
+
+.. htsql:: /school.department
+   :hide:
+
+.. htsql:: /program.school
+   :hide:
+
+.. htsql:: /school.program
+   :hide:
+
+.. htsql:: /course.department
+   :hide:
+
+.. htsql:: /department.course
+   :hide:
+
+A foreign key ``program_part_of_fk`` induces two self-referential links
+on ``program``:
+
+.. htsql:: /program.part_of
+   :hide:
+
+.. htsql:: /program.program_via_part_of
+   :hide:
 
 
 .. vim: set spell spelllang=en textwidth=72:
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.