diff --git a/doc/slide/code-reading-201601/SourceTreeJ.html b/doc/slide/code-reading-201601/SourceTreeJ.html index 13ac3397..b991646a 100644 --- a/doc/slide/code-reading-201601/SourceTreeJ.html +++ b/doc/slide/code-reading-201601/SourceTreeJ.html @@ -4,6 +4,7 @@ +
$$\{ (x, y) | x \in X, y \in Y, \pi_1(x) = \pi_2(y) \}$$
--- Comprehension
+-- Comprehension
[ (x, y) | x <- xs, y <- ys, fst x == snd y ]
-- List Monad
-do { x <- xs; y <- ys; fst x == snd y; return (x, y) }
+do { x <- xs; y <- ys; guard (fst x == snd y); return (x, y) }
結合クエリを List内包表記あるいは List Monad のように組み立てる
-personAndBirthday :: Relation () (Person, Birthday)
+personAndBirthday :: Relation () (Person, Birthday)
personAndBirthday = relation $ do
p <- query person -- Join product accumulated
b <- query birthday
on $ p ! Person.name' .=. b ! Birthday.name'
- return $ p >< b
+ return $ p >< b
personAndBirthday :: Relation () (Person, Birthday)
+personAndBirthday :: Relation () (Person, Birthday)
personAndBirthday = relation $ do
p <- query person
- b <- query birthday -- 結合積の集積
+ b <- query birthday -- 結合積の集積
-- Join product accumulated
on $ p ! Person.name' .=. b ! Birthday.name'
- return $ p >< b
-SELECT ALL T0.name AS f0, T0.age AS f1, T0.family AS f2,
+ return $ p >< b
+SELECT ALL T0.name AS f0, T0.age AS f1, T0.family AS f2,
T1.name AS f3, T1.day AS f4
FROM EXAMPLE.person T0 INNER JOIN EXAMPLE.birthday T1
- ON (T0.name = T1.name)
+ ON (T0.name = T1.name)
query :: (MonadQualify ConfigureQuery m, MonadQuery m)
+query :: (MonadQualify ConfigureQuery m, MonadQuery m)
=> Relation () r
-> m (Projection Flat r)
-- Used for outer join
queryMaybe :: (MonadQualify ConfigureQuery m, MonadQuery m)
=> Relation () r
- -> m (Projection Flat (Maybe r))
+ -> m (Projection Flat (Maybe r))
query
, queryMaybe
は結合したテーブル式の Projection
を返す
-SELECT .. FROM ...
+SELECT .. FROM ...
-- Accumulating uniquely qualified
-- ( like 'as T0', 'as T1' ... )
- -- table forms of SQL FROM clause
+ -- table forms of SQL FROM clause
personAndBirthdayL :: Relation () (Person, Maybe Birthday)
+personAndBirthdayL :: Relation () (Person, Maybe Birthday)
personAndBirthdayL = relation $ do
p <- query person
b <- queryMaybe birthday
on $ just (p ! Person.name') .=. b ?! Birthday.name'
- return $ p >< b
-SELECT ALL T0.name AS f0, T0.age AS f1, T0.family AS f2,
+ return $ p >< b
+SELECT ALL T0.name AS f0, T0.age AS f1, T0.family AS f2,
T1.name AS f3, T1.day AS f4
FROM EXAMPLE.person T0 LEFT JOIN EXAMPLE.birthday T1
- ON (T0.name = T1.name)
+ ON (T0.name = T1.name)
groupBy :: MonadAggregate m
+groupBy :: MonadAggregate m
=> Projection Flat r
-- ^ Projection to add into group by
-> m (Projection Aggregated r)
@@ -119,53 +138,53 @@ personAndBirthdayL = relation $
count :: Projection Flat a -> Projection Aggregated Int64
max' :: Ord a
- => Projection Flat a -> Projection Aggregated (Maybe a)
+ => Projection Flat a -> Projection Aggregated (Maybe a)
groupBy
は MonadAggregate
の monad 制約 (MonadQuery
より制限が強い)の下でのみ利用できる。
groupBy
は集約した(Aggregated)文脈の型を持つ Projection
の値を返す。
-SELECT .. GROUP BY ...
+SELECT .. GROUP BY ...
-- Accumulating keys
- -- of SQL GROUP BY clause
+ -- of SQL GROUP BY clause
agesOfFamilies :: Relation () (String, Maybe Int32)
+agesOfFamilies :: Relation () (String, Maybe Int32)
agesOfFamilies = aggregateRelation $ do
p <- query person
gFam <- groupBy $ p ! Person.family'
-- Specify grouping key
return $ gFam >< sum' (p ! Person.age')
- -- Aggregated results
-SELECT ALL T0.family AS f0, SUM(T0.age) AS f1
+ -- Aggregated results
+SELECT ALL T0.family AS f0, SUM(T0.age) AS f1
FROM EXAMPLE.person T0
- GROUP BY T0.family
+ GROUP BY T0.family
restrict :: MonadRestrict c m
+restrict :: MonadRestrict c m
=> Projection c (Maybe Bool)
-> m ()
wheres :: MonadRestrict Flat m
=> Projection Flat (Maybe Bool)
- -> m ()
+ -> m ()
WHERE 節に絞り込み条件を加える
-SELECT .. WHERE x AND y AND ...
+SELECT .. WHERE x AND y AND ...
-- Accumulating AND predicates
- -- of SQL WHERE clause
+ -- of SQL WHERE clause
restrict :: MonadRestrict c m
+restrict :: MonadRestrict c m
=> Projection c (Maybe Bool)
-> m ()
having :: MonadRestrict Aggregated m
=> Projection Aggregated (Maybe Bool)
- -> m ()
+ -> m ()
HAVING 節に絞り込み条件を加える。 集約した(Aggregated)文脈の型を持つ Projection
のみが利用できる
-SELECT .. HAVING x AND y AND ...
+SELECT .. HAVING x AND y AND ...
-- Accumulating AND predicates
- -- of SQL HAVING clause
+ -- of SQL HAVING clause
sameBirthdayHeisei' :: Relation () (Day, Int64)
+sameBirthdayHeisei' :: Relation () (Day, Int64)
sameBirthdayHeisei' = aggregateRelation $ do
p <- query person
b <- query birthday
@@ -174,7 +193,7 @@ sameBirthdayHeisei' = aggregateRelation ! Birthday.day' .>=. value (fromGregorian 1989 1 8)
gbd <- groupBy $ b ! Birthday.day'
having $ count (p ! Person.name') .>. value (1 :: Int64)
- return $ gbd >< count (p ! Person.name')
+ return $ gbd >< count (p ! Person.name')
平成生まれで誕生日が同じ人を数える
-
SELECT ALL T1.day AS f0, COUNT(T0.name) AS f1
+SELECT ALL T1.day AS f0, COUNT(T0.name) AS f1
FROM EXAMPLE.person T0 INNER JOIN EXAMPLE.birthday T1
ON (T0.name = T1.name)
WHERE (T1.day >= DATE '1989-01-08')
GROUP BY T1.day
- HAVING (COUNT(T0.name) > 1)
+ HAVING (COUNT(T0.name) > 1)
sameBirthdayHeisei :: Relation () (Day, Int64)
+sameBirthdayHeisei :: Relation () (Day, Int64)
sameBirthdayHeisei = aggregateRelation $ do
p <- query person
b <- query birthday
@@ -207,81 +225,81 @@ sameBirthdayHeisei = aggregateRelation <- groupBy birthDay
let personCount = count $ p ! Person.name'
having $ personCount .>. value 1
- return $ gbd >< personCount
+ return $ gbd >< personCount
orderBy :: Monad m
+orderBy :: Monad m
=> Projection c t
-- ^ Ordering terms to add
-> Order
-- ^ Order direction -- Asc | Desc
-> Orderings c m ()
- -- ^ Result context with ordering
+ -- ^ Result context with ordering
文脈に合わせた Projection
の型を持った値のみが利用できる。
-SELECT .. ORDER BY ...
- -- Accumulating terms of ORDER BY clause
+SELECT .. ORDER BY ...
+ -- Accumulating terms of ORDER BY clause
personAndBirthdayO :: Relation () (Person, Birthday)
+personAndBirthdayO :: Relation () (Person, Birthday)
personAndBirthdayO = relation $ do
p <- query person
b <- query birthday
on $ p ! Person.name' .=. b ! Birthday.name'
orderBy (b ! Birthday.day') Asc -- Specify ordering key
orderBy (p ! Person.name') Asc
- return $ p >< b
+ return $ p >< b
orders by birthday and then name:
-SELECT ALL T0.name AS f0, T0.age AS f1, T0.family AS f2,
+SELECT ALL T0.name AS f0, T0.age AS f1, T0.family AS f2,
T1.name AS f3, T1.day AS f4
FROM EXAMPLE.person T0 INNER JOIN EXAMPLE.birthday T1
ON (T0.name = T1.name)
- ORDER BY T1.day ASC, T0.name ASC
+ ORDER BY T1.day ASC, T0.name ASC
SELECT ALL T0.name AS f0, T0.age AS f1, T0.family AS f2,
+SELECT ALL T0.name AS f0, T0.age AS f1, T0.family AS f2,
T1.name AS f3, T1.day AS f4
FROM EXAMPLE.person T0 INNER JOIN EXAMPLE.birthday T1
ON (T0.name = T1.name)
- ORDER BY T1.day ASC, T0.name ASC
+ ORDER BY T1.day ASC, T0.name ASC
placeholder ::
+placeholder ::
(PersistableWidth t, SqlProjectable p, Monad m) =>
- (p t -> m a) -> m (PlaceHolders t, a)
+ (p t -> m a) -> m (PlaceHolders t, a)
組み立てのモナドの式に placeholder を与える
specifyPerson :: Relation String (Person, Birthday)
+specifyPerson :: Relation String (Person, Birthday)
specifyPerson = relation' $ do
pb <- query personAndBirthday -- Re-use predefined
(ph, ()) <- placeholder
(\ph' ->
wheres $ pb ! fst' ! Person.name' .=. ph')
- return (ph, pb)
+ return (ph, pb)
名前をプレースホルダーで指定する:
-SELECT ALL T2.f0 AS f0, T2.f1 AS f1, T2.f2 AS f2,
+SELECT ALL T2.f0 AS f0, T2.f1 AS f1, T2.f2 AS f2,
T2.f3 AS f3, T2.f4 AS f4
FROM (SELECT ALL T0.name AS f0, T0.age AS f1, T0.family AS f2,
T1.name AS f3, T1.day AS f4
FROM EXAMPLE.person T0 INNER JOIN
EXAMPLE.birthday T1
ON (T0.name = T1.name)) T2
- WHERE (T2.f0 = ?)
+ WHERE (T2.f0 = ?)
SELECT ALL T2.f0 AS f0, T2.f1 AS f1, T2.f2 AS f2,
+SELECT ALL T2.f0 AS f0, T2.f1 AS f1, T2.f2 AS f2,
T2.f3 AS f3, T2.f4 AS f4
FROM (SELECT ALL T0.name AS f0, T0.age AS f1, T0.family AS f2,
T1.name AS f3, T1.day AS f4
FROM EXAMPLE.person T0 INNER JOIN
EXAMPLE.birthday T1
ON (T0.name = T1.name)) T2
- WHERE (T2.f0 = ?)
+ WHERE (T2.f0 = ?)
ウィンドウを組み立てる:
Building windows:
-ageRankOfFamilies :: Relation () ((Int64, String), Int32)
+ageRankOfFamilies :: Relation () ((Int64, String), Int32)
ageRankOfFamilies = relation $ do
my <- query myTable
return $
@@ -289,34 +307,34 @@ ageRankOfFamilies = relation $
partitionBy $ my ! family' -- Monad to build window
orderBy (my ! age') Desc
><
- my ! family' >< my ! age'
-SELECT ALL
+ my ! family' >< my ! age'
+SELECT ALL
RANK() OVER (PARTITION BY T0.family
ORDER BY T0.age DESC) AS f0,
T0.family AS f1, T0.age AS f2
- FROM PUBLIC.my_table T0
+ FROM PUBLIC.my_table T0
SELECT ALL
+SELECT ALL
RANK() OVER (PARTITION BY T0.family
ORDER BY T0.age DESC) AS f0,
T0.family AS f1, T0.age AS f2
- FROM PUBLIC.my_table T0
+ FROM PUBLIC.my_table T0
Mapping to records using Applicative style:
-(|$|) :: (ProjectableFunctor p, ProductConstructor (a -> b))
+(|$|) :: (ProjectableFunctor p, ProductConstructor (a -> b))
=> (a -> b)
-> p a
-> p b
(|*|) :: ProjectableApplicative p
=> p (a -> b)
-> p a
- -> p b
+ -> p b
Assign record types to an SQL projection:
-personAndBirthdayT :: Relation () PersonAndBirthday
+personAndBirthdayT :: Relation () PersonAndBirthday
personAndBirthdayT = relation $ do
p <- query person
b <- query birthday
@@ -326,26 +344,26 @@ personAndBirthdayT = relation $
(|$|) :: ProductConstructor (a -> b)
=> (a -> b) -> Projection c a -> Projection c b
-(|*|) :: Projection c (a -> b) -> Projection c a -> Projection c b
-SELECT ALL T0.name AS f0, T0.age AS f1, T0.address AS f2,
+(|*|) :: Projection c (a -> b) -> Projection c a -> Projection c b
+SELECT ALL T0.name AS f0, T0.age AS f1, T0.address AS f2,
T1.name AS f3, T1.day AS f4
FROM PUBLIC.person T0 INNER JOIN PUBLIC.birthday T1
- ON (T0.name = T1.name)
+ ON (T0.name = T1.name)
Column selectors can be mapped to a record:
-Birthday.day' :: Pi Birthday Day
+Birthday.day' :: Pi Birthday Day
uncurryPB :: Pi (Person, Birthday) PersonAndBirthday
uncurryPB = PersonAndBirthday |$| fst' |*| snd'
(|$|) :: ProductConstructor (a -> b)
=> (a -> b) -> Pi r a -> Pi r b
-(|*|) :: Pi r (a -> b) -> Pi r a -> Pi r b
+(|*|) :: Pi r (a -> b) -> Pi r a -> Pi r b
Placeholders can be mapped to a record:
-personAndBirthdayP2 :: Relation Person PersonAndBirthday
+personAndBirthdayP2 :: Relation Person PersonAndBirthday
personAndBirthdayP2 = relation' $ do
p <- query person
b <- query birthday
@@ -358,23 +376,23 @@ personAndBirthdayP2 = relation' $(|$|) :: ProductConstructor (a -> b)
=> (a -> b) -> Placeholders a -> Placeholders b
-(|*|) :: Placeholders (a -> b) -> Placeholders a -> Placeholders b
+(|*|) :: Placeholders (a -> b) -> Placeholders a -> Placeholders b
Generated SQL:
-SELECT ALL T0.name AS f0, T0.age AS f1, T0.address AS f2,
+SELECT ALL T0.name AS f0, T0.age AS f1, T0.address AS f2,
T1.name AS f3, T1.day AS f4
FROM PUBLIC.person T0 INNER JOIN PUBLIC.birthday T1
- ON (((T0.name = ?) AND (T0.age = ?)) AND (T0.address = ?))
+ ON (((T0.name = ?) AND (T0.age = ?)) AND (T0.address = ?))
Generated SQL:
-SELECT ALL T0.name AS f0, T0.age AS f1, T0.address AS f2,
+SELECT ALL T0.name AS f0, T0.age AS f1, T0.address AS f2,
T1.name AS f3, T1.day AS f4
FROM PUBLIC.person T0 INNER JOIN PUBLIC.birthday T1
- ON (((T0.name = ?) AND (T0.age = ?)) AND (T0.address = ?))
+ ON (((T0.name = ?) AND (T0.age = ?)) AND (T0.address = ?))
Record-typed placeholder:
-placeholder :: (PersistableWidth t, Monad m)
+placeholder :: (PersistableWidth t, Monad m)
=> (Projection c t -> m a) -> m (PlaceHolders t, a)
personAndBirthdayP :: Relation Person PersonAndBirthday
@@ -382,12 +400,12 @@ personAndBirthdayP = relation' $<- query person
b <- query birthday
(ph, ()) <- placeholder (\ph' -> wheres $ p .=. ph')
- return $ (ph, PersonAndBirthday |$| p |*| b)
+ return $ (ph, PersonAndBirthday |$| p |*| b)
row value of Placeholders:
-SELECT ALL T0.name AS f0, T0.age AS f1, T0.address AS f2,
+SELECT ALL T0.name AS f0, T0.age AS f1, T0.address AS f2,
T1.name AS f3, T1.day AS f4
FROM PUBLIC.person T0 INNER JOIN PUBLIC.birthday T1
- ON ((T0.name, T0.age, T0.address) = (?, ?, ?))
+ ON ((T0.name, T0.age, T0.address) = (?, ?, ?))