on master help sign in
more docs updates to reflect new runtime types
b5a555cAgentM
docs/15_minute_tutorial.markdown+2
@@ -282,6 +282,8 @@ Now we have jumped back to the master branch and we can confirm that the "employ
282
282
283Of course, Project:M36 supports [aggregate operators](docs/tutd_tutorial.markdown#aggregate-queries), [value functions](docs/tutd_tutorial.markdown#extend), [database constraints](docs/tutd_tutorial.markdown#constraints) including candidate and foreign keys, and other operators not mentioned in this brief tutorial.
283Of course, Project:M36 supports [aggregate operators](docs/tutd_tutorial.markdown#aggregate-queries), [value functions](docs/tutd_tutorial.markdown#extend), [database constraints](docs/tutd_tutorial.markdown#constraints) including candidate and foreign keys, and other operators not mentioned in this brief tutorial.
284
284
285+While this tutorial only covered an in-memory database, Project:M36 also supports ACID-compliant filesystem persistence as well as [server-based operation](docs/server_mode.markdown).
286+
285## Conclusion
287## Conclusion
286
288
287The TutorialD dialect used by Project:M36 is ideal for learning about the relational algebra because it is quick to write and grammatically unambiguous.
289The TutorialD dialect used by Project:M36 is ideal for learning about the relational algebra because it is quick to write and grammatically unambiguous.
docs/new_datatypes.markdown+34−3
@@ -2,17 +2,48 @@
2
2
3## Introduction
3## Introduction
4
4
5−The most common data types are built into Project:M36 directly. Such types include integers, text, byte strings, booleans and floats. It can often be handy to create one's own data types in a database and manipulate them as first-class values through the relational algebra.
5+The most common data types are built into Project:M36 directly. Such types include integers, text, byte strings, booleans and floats. It can often be handy to create one's own data types in a database and manipulate them as first-class values through the relational algebra.
6+
7+In addition, the Project:M36 runtime supports algebraic data types in the same vein as Haskell itself.
6
8
7Project:M36 makes it easy to add any Haskell data type to the database. Any type which includes instances for a set of typeclasses can be supported.
9Project:M36 makes it easy to add any Haskell data type to the database. Any type which includes instances for a set of typeclasses can be supported.
8
10
9−## Support
11+## Support for Runtime Types
12+
13+Use the ```tutd``` interpreter to create new type and data constructors with essentially the same syntax as in Haskell:
14+
15+```
16+TutorialD (master): data Hair = Bald | Brown | Blond | OtherColor Text
17+TutorialD (master): :showexpr relation{tuple{name "Steve", hair Blond}, tuple{name "Sam", hair OtherColor "Grey"}}
18+┌─────────────────┬──────────┐
19+│hair::Hair │name::Text│
20+├─────────────────┼──────────┤
21+│Blond │"Steve" │
22+│OtherColor "Grey"│"Sam" │
23+└─────────────────┴──────────┘
24+```
25+
26+SQL's enumerations or even joins do not compare favorably to a genuine algebraic data type. Exercise for the reader: why is this? Do you agree?
27+
28+Types can be forgotten as well:
29+
30+```
31+TutorialD (master): undata Hair
32+```
33+
34+These runtime types can therefore change between transactions. Note that the underlying data values do not change when the types change. Once changed, only new values will reflect the new data constructors.
35+
36+The downside to this approach is that functions which operate on these runtime types cannot be written in the TutorialD interpreter (yet).
37+
38+Note that the Haskell-standard "Maybe a" and "Either a b" data types are included by default.
39+
40+## Support for Haskell Types
10
41
11Any Haskell data type which is an instance of ```Atomable``` is a candidate for a Project:M36 value called an ```Atom```. Database tuples are composed of Atoms.
42Any Haskell data type which is an instance of ```Atomable``` is a candidate for a Project:M36 value called an ```Atom```. Database tuples are composed of Atoms.
12
43
13Project:M36 does not yet support dynamically-loaded components, so the data type must be compiled into the Project:M36 backend.
44Project:M36 does not yet support dynamically-loaded components, so the data type must be compiled into the Project:M36 backend.
14
45
15−### Implementation
46+### Implementation for Haskell Types
16
47
171. Create an instance of your data type for the ```Atomable``` typeclass. The ```Atomable``` typeclass implies instances for a variety of standard typeclasses.
481. Create an instance of your data type for the ```Atomable``` typeclass. The ```Atomable``` typeclass implies instances for a variety of standard typeclasses.
181. Update the ```Binary Atom``` instance to include deserialization for your type.
491. Update the ```Binary Atom``` instance to include deserialization for your type.
docs/on_null.markdown+64−36
@@ -10,9 +10,9 @@ SQL intentionally differentiates NULL from all other values. NULL is not an inte
10
10
11```
11```
12postgres=# select NULL = NULL;
12postgres=# select NULL = NULL;
13− ?column?
13+ ?column?
14----------
14----------
15−
15+
16(1 row)
16(1 row)
17```
17```
18
18
@@ -68,7 +68,7 @@ postgres=# select * from x where a=a;
68Example 3: Return all rows where b is from a list of NULL.
68Example 3: Return all rows where b is from a list of NULL.
69```
69```
70postgres=# select * from x where b = any(NULL);
70postgres=# select * from x where b = any(NULL);
71− a | b
71+ a | b
72---+---
72---+---
73(0 rows)
73(0 rows)
74```
74```
@@ -101,7 +101,7 @@ postgres=# select * from x where exists (SELECT * FROM x as y where (a,b) = (y.a
101(3 rows)
101(3 rows)
102````
102````
103
103
104−All of the above query examples conform to the SQL standard with regards to NULL handling.
104+All of the above query examples conform to the SQL standard with regards to NULL handling.
105
105
106
106
107## Inconsistencies Leading to Errors
107## Inconsistencies Leading to Errors
@@ -110,8 +110,8 @@ If the difference between NULL handling in ```ANY``` versus ```EXISTS``` didn't
110
110
111Example 7: Aggregate a sum over a in x where one a value is NULL.
111Example 7: Aggregate a sum over a in x where one a value is NULL.
112```
112```
113−postgres=# select sum(a) from x;
113+postgres=# select sum(a) from x;
114− sum
114+ sum
115-----
115-----
116 3
116 3
117(1 row)
117(1 row)
@@ -119,20 +119,20 @@ postgres=# select sum(a) from x;
119Example 8: Aggregate a sum over two NULLs.
119Example 8: Aggregate a sum over two NULLs.
120```
120```
121postgres=# select sum(a) from (values (NULL::int),(NULL)) as y(a); --sum of only NULLs is NULL
121postgres=# select sum(a) from (values (NULL::int),(NULL)) as y(a); --sum of only NULLs is NULL
122− sum
122+ sum
123-----
123-----
124−
124+
125(1 row)
125(1 row)
126```
126```
127Example 9: Count the number of a values in x. Count the number of rows in x.
127Example 9: Count the number of a values in x. Count the number of rows in x.
128```
128```
129postgres=# select count(a) from x;
129postgres=# select count(a) from x;
130− count
130+ count
131-------
131-------
132 2
132 2
133(1 row)
133(1 row)
134postgres=# select count(*) from x;
134postgres=# select count(*) from x;
135− count
135+ count
136-------
136-------
137 3
137 3
138(1 row)
138(1 row)
@@ -142,17 +142,17 @@ Example 10: Aggregate the sum of an empty table.
142postgres=# create table z(a int);
142postgres=# create table z(a int);
143CREATE TABLE
143CREATE TABLE
144postgres=# select sum(a) from z; -- sum of empty table is NULL
144postgres=# select sum(a) from z; -- sum of empty table is NULL
145− sum
145+ sum
146-----
146-----
147−
147+
148(1 row)
148(1 row)
149```
149```
150Example 11: NULL multipled by zero plus three.
150Example 11: NULL multipled by zero plus three.
151```
151```
152postgres=# select 0*NULL + 3;
152postgres=# select 0*NULL + 3;
153− ?column?
153+ ?column?
154----------
154----------
155−
155+
156(1 row)
156(1 row)
157```
157```
158
158
@@ -161,9 +161,9 @@ This logic follows into arrays:
161Example 12: Is NULL equal to any element in the array?
161Example 12: Is NULL equal to any element in the array?
162```
162```
163postgres=# select NULL = ANY(array[1,2,3,NULL]);
163postgres=# select NULL = ANY(array[1,2,3,NULL]);
164− ?column?
164+ ?column?
165----------
165----------
166−
166+
167(1 row)
167(1 row)
168```
168```
169
169
@@ -172,13 +172,13 @@ and row-valued expressions:
172Example 13: Is the (NULL,1) tuple equal to NULL? Is it not equal to NULL?
172Example 13: Is the (NULL,1) tuple equal to NULL? Is it not equal to NULL?
173```
173```
174postgres=# select (NULL,1) is null;
174postgres=# select (NULL,1) is null;
175− ?column?
175+ ?column?
176----------
176----------
177 f
177 f
178(1 row)
178(1 row)
179
179
180postgres=# select (NULL,1) is not null;
180postgres=# select (NULL,1) is not null;
181− ?column?
181+ ?column?
182----------
182----------
183 f
183 f
184(1 row)
184(1 row)
@@ -193,12 +193,12 @@ SQL does not enforce the relational model constraint that rows (tuples) be uniqu
193Example 14: Create multiple NULLs in a result set.
193Example 14: Create multiple NULLs in a result set.
194```
194```
195postgres=# select * from (values (34),(50),(NULL),(NULL)) as employee_age(val);
195postgres=# select * from (values (34),(50),(NULL),(NULL)) as employee_age(val);
196− val
196+ val
197-----
197-----
198 34
198 34
199 50
199 50
200−
200+
201−
201+
202(4 rows)
202(4 rows)
203```
203```
204
204
@@ -222,14 +222,14 @@ postgres=# insert into z(a,b) values (2,'two'),(NULL,NULL) returning a,b;
222 a | b
222 a | b
223---+-----
223---+-----
224 2 | two
224 2 | two
225− |
225+ |
226(2 rows)
226(2 rows)
227postgres=# select x.a as xa,x.b as xb,z.a as za,z.b as zb from x left join z on x.a is not distinct from z.a;
227postgres=# select x.a as xa,x.b as xb,z.a as za,z.b as zb from x left join z on x.a is not distinct from z.a;
228 xa | xb | za | zb
228 xa | xb | za | zb
229----+-------+----+-----
229----+-------+----+-----
230− 1 | one | |
230+ 1 | one | |
231 2 | two | 2 | two
231 2 | two | 2 | two
232− | three | |
232+ | three | |
233(3 rows)
233(3 rows)
234
234
235```
235```
@@ -306,7 +306,7 @@ and some examples values:
306* ```PreciseAge 25```
306* ```PreciseAge 25```
307* ```NotApplicable```
307* ```NotApplicable```
308* ```ApproximateAge 30 40``` approximately between 30-40 years old
308* ```ApproximateAge 30 40``` approximately between 30-40 years old
309−
309+
310Already, we can see that this single data type can pack far more useful information than any combination of an integer and NULL.
310Already, we can see that this single data type can pack far more useful information than any combination of an integer and NULL.
311
311
312### Algebraic Data Types In SQL
312### Algebraic Data Types In SQL
@@ -317,8 +317,8 @@ An algebraic data type may be emulated in SQL, albeit in a convoluted fashion an
317postgres=# create type age_type as enum ('precise_age', 'forgot_to_ask', 'refused_to_disclose', 'not_applicable', 'approximate_age');
317postgres=# create type age_type as enum ('precise_age', 'forgot_to_ask', 'refused_to_disclose', 'not_applicable', 'approximate_age');
318CREATE TYPE
318CREATE TYPE
319
319
320−postgres=# create table hospital_patient(name text not null,
320+postgres=# create table hospital_patient(name text not null,
321− age age_type not null,
321+ age age_type not null,
322 precise_age int,
322 precise_age int,
323 approximate_age int[2]);
323 approximate_age int[2]);
324postgres=# insert into hospital_patient(name,age,precise_age,approximate_age) values ('Bob','approximate_age',NULL,array[30,40]);
324postgres=# insert into hospital_patient(name,age,precise_age,approximate_age) values ('Bob','approximate_age',NULL,array[30,40]);
@@ -342,6 +342,38 @@ But all we have really done is add even more NULLs. Retrieving a sensible value
342
342
343### Algebraic Data Types In Project:M36
343### Algebraic Data Types In Project:M36
344
344
345+## Runtime Types
346+
347+Project:M36 supports management of new algebraic data types at runtime. These types are associated with transactions and can changed over time whereas primitive Atoms cannot be changed.
348+d
349+```
350+TutorialD (master): data Age = PreciseAge Int | ForgotToAsk | RefusedToDisclose | NotApplicable | ApproximateAge Int Int
351+TutorialD (master): :showexpr relation{tuple{name "Steve", age ApproximateAge 20 30}, tuple{name "Bob", age RefusedToDisclose}, tuple {name "Initech Corp.", age NotApplicable}}
352+┌────────────────────┬───────────────┐
353+│age::Age │name::Text │
354+├────────────────────┼───────────────┤
355+│ApproximateAge 20 30│"Steve" │
356+│NotApplicable │"Initech Corp."│
357+│RefusedToDisclose │"Bob" │
358+└────────────────────┴───────────────┘
359+```
360+
361+Note that the two values which would normally be rendered as NULL in SQL are indeed proper values and can be distinguished. Three-valued logic makes no appearance. The type constructors can also have arguments:
362+
363+```
364+TutorialD (master): data Tree a = Node a (Tree a) (Tree a) | EmptyNode
365+TutorialD (master): :showexpr relation{tuple{family "Stevenson", familytree Node "Jim" (Node "Cindy" EmptyNode EmptyNode) (Node "Mike" EmptyNode EmptyNode)}}
366+┌────────────┬───────────────────────────────────────────────────────────────────────────────┐
367+│family::Text│familytree::Tree (a::Text) │
368+├────────────┼───────────────────────────────────────────────────────────────────────────────┤
369+│"Stevenson" │Node "Jim" (Node "Cindy" EmptyNode EmptyNode) (Node "Mike" EmptyNode EmptyNode)│
370+└────────────┴───────────────────────────────────────────────────────────────────────────────┘
371+```
372+
373+Algebraic data types in SQL are effectively impossible.
374+
375+## Haskell Types
376+
345Any Haskell data type can be turned into a value (called an "atom") in Project:M36. The following example illustrates:
377Any Haskell data type can be turned into a value (called an "atom") in Project:M36. The following example illustrates:
346
378
347```haskell
379```haskell
@@ -365,7 +397,7 @@ data AgeType = PreciseAge Int |
365 NotApplicable |
397 NotApplicable |
366 ApproximateAge Int Int
398 ApproximateAge Int Int
367 deriving (Eq,Show,Read,Hashable,Binary,Typeable,NFData,Generic)
399 deriving (Eq,Show,Read,Hashable,Binary,Typeable,NFData,Generic)
368−
400+
369instance Atomable AgeType
401instance Atomable AgeType
370
402
371failFastMaybe :: (Show a) => Maybe a -> IO ()
403failFastMaybe :: (Show a) => Maybe a -> IO ()
@@ -378,15 +410,15 @@ failFastEither (Right val) = return val
378
410
379ageAtomType :: AtomType
411ageAtomType :: AtomType
380ageAtomType = atomTypeForProxy (Proxy :: Proxy AgeType)
412ageAtomType = atomTypeForProxy (Proxy :: Proxy AgeType)
381−
413+
382runExample :: IO ()
414runExample :: IO ()
383runExample = do
415runExample = do
384 let bob_relation_attrs = attributesFromList [Attribute "name" stringAtomType,
416 let bob_relation_attrs = attributesFromList [Attribute "name" stringAtomType,
385 Attribute "age" ageAtomType]
417 Attribute "age" ageAtomType]
386 relvar_name = "hospital_patient"
418 relvar_name = "hospital_patient"
387− age_value_in = ApproximateAge 30 40
419+ age_value_in = ApproximateAge 30 40
388− bob_relation_err = mkRelationFromList
420+ bob_relation_err = mkRelationFromList
389− bob_relation_attrs
421+ bob_relation_attrs
390 [[Atom ("Bob"::Text), Atom age_value_in]]
422 [[Atom ("Bob"::Text), Atom age_value_in]]
391
423
392 connerr <- connectProjectM36 (InProcessConnectionInfo NoPersistence)
424 connerr <- connectProjectM36 (InProcessConnectionInfo NoPersistence)
@@ -427,7 +459,3 @@ Regardless, modeling the fact that some information may be missing is valuable,
427Date, C.J. Darwen, Hugh. [Database Explorations: Essays on the Third Manifesto and Related Topics](http://bookstore.trafford.com/Products/SKU-000177853/Database-Explorations.aspx) chapters 23-29
459Date, C.J. Darwen, Hugh. [Database Explorations: Essays on the Third Manifesto and Related Topics](http://bookstore.trafford.com/Products/SKU-000177853/Database-Explorations.aspx) chapters 23-29
428
460
429Date, C.J. [Database in Depth](http://bookstore.trafford.com/Products/SKU-000177853/Database-Explorations.aspx) pages 53-55
461Date, C.J. [Database in Depth](http://bookstore.trafford.com/Products/SKU-000177853/Database-Explorations.aspx) pages 53-55
430−
431−
432−
433−