haskell-relational-record/doc/slide/tsukuba-201412/DSL.html

442 lines
257 KiB
HTML
Raw Normal View History

2014-12-24 11:58:51 +03:00
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
2016-09-17 10:01:05 +03:00
<meta name="version" content="S5 1.1" />
<meta name="author" content="2014-12-25 (Updated 2014-12-29)" />
2014-12-24 13:45:21 +03:00
<title>Haskell Relational Record's Query-Building DSL</title>
2014-12-24 11:58:51 +03:00
<style type="text/css">code{white-space: pre;}</style>
<!-- configuration parameters -->
<meta name="defaultView" content="slideshow" />
<meta name="controlVis" content="hidden" />
<style type="text/css">
2016-09-17 10:01:05 +03:00
div.sourceCode { overflow-x: auto; }
2014-12-24 11:58:51 +03:00
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
2016-09-17 10:01:05 +03:00
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
2014-12-24 11:58:51 +03:00
</style>
<!-- style sheet links -->
2016-09-17 10:01:05 +03:00
<link href="data:text/css;charset=utf-8,%40import%20url%28data%3Atext%2Fcss%3Bcharset%3Dutf%2D8%2C%250Adiv%2523header%252C%2520div%2523footer%252C%2520div%2523controls%252C%2520%252Eslide%2520%257Bposition%253A%2520absolute%253B%257D%250Ahtml%253Ebody%2520div%2523header%252C%2520html%253Ebody%2520div%2523footer%252C%2520html%253Ebody%2520div%2523controls%252C%2520html%253Ebody%2520%252Eslide%2520%257Bposition%253A%2520fixed%253B%257D%250A%252Ehandout%2520%257Bdisplay%253A%2520none%253B%257D%250A%252Elayout%2520%257Bdisplay%253A%2520block%253B%257D%250A%252Eslide%252C%2520%252Ehideme%252C%2520%252Eincremental%2520%257Bvisibility%253A%2520hidden%253B%257D%250A%2523slide0%2520%257Bvisibility%253A%2520visible%253B%257D%250A%29%3B%20%0A%40import%20url%28data%3Atext%2Fcss%3Bcharset%3Dutf%2D8%2C%250A%250Adiv%2523header%252C%2520div%2523footer%252C%2520%252Eslide%2520%257Bwidth%253A%2520100%2525%253B%2520top%253A%25200%253B%2520left%253A%25200%253B%257D%250Adiv%2523header%2520%257Btop%253A%25200%253B%2520height%253A%25203em%253B%2520z%252Dindex%253A%25201%253B%257D%250Adiv%2523footer%2520%257Btop%253A%2520auto%253B%2520bottom%253A%25200%253B%2520height%253A%25202%252E5em%253B%2520z%252Dindex%253A%25205%253B%257D%250A%252Eslide%2520%257Btop%253A%25200%253B%2520width%253A%252092%2525%253B%2520padding%253A%25203%252E5em%25204%2525%25204%2525%253B%2520z%252Dindex%253A%25202%253B%2520list%252Dstyle%253A%2520none%253B%257D%250Adiv%2523controls%2520%257Bleft%253A%252050%2525%253B%2520bottom%253A%25200%253B%2520width%253A%252050%2525%253B%2520z%252Dindex%253A%2520100%253B%257D%250Adiv%2523controls%2520form%2520%257Bposition%253A%2520absolute%253B%2520bottom%253A%25200%253B%2520right%253A%25200%253B%2520width%253A%2520100%2525%253B%250Amargin%253A%25200%253B%257D%250A%2523currentSlide%2520%257Bposition%253A%2520absolute%253B%2520width%253A%252010%2525%253B%2520left%253A%252045%2525%253B%2520bottom%253A%25201em%253B%2520z%252Dindex%253A%252010%253B%257D%250Ahtml%253Ebody%2520%2523currentSlide%2520%257Bposition%253A%2520fixed%253B%257D%250A%250A%29%3B%20%0A%40import%20url%28data%3Atext%2Fcss%3Bcharset%3Dutf%2D8%2C%250Abody%2520%257Bbackground%253A%2520%2523FFF%2520url%2528data%253Aimage%252Fgif%253Bbase64%252CR0lGODlh5gBOAcT%252FAMDAwLW1tb29vcbGxs7OztbW1t7e3ufn5%252B%252Fv7%252Ff39%252Bfv7%252B%252F39%252Ff%252F%252F8bOzs7W1tbe3t7n57W9vb3Gxuf3987e3tbn597v78bW1r3Ozs7n5wAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAADmAE4BAAX%252F4CEez3UZ1PNAjppCpALM9GxNgLXUfD8pC6BC1mMoLApGb7nUMRaWBLOmwAGOREVlqK38LNNwbQIWm2fH2aLScJzf8NqI1Lg8Cqq6w9EoOAwPZT0KFBkIcVhkSwlQh3E8EDhrOmELFEQ5VTMJRwwQDTtXFRlbj2hRWwkZhZhMDBVINQsZMrMUgqa5PHMiDw0qdg8igIAOUjxrVo9YEE0VFaG6sZ5Imj2zuFxFFBQ1Smm5UAATzeJhnkEV1%252BqWF8268DO8JA8GbcIjD3%252FvsrQIuGegKFkyJJ4NIhAoUULGb8aEZwQlDER2a0o0WdDeLYCQACCNIwsflqKxZpyECx4N%252F77hpW9ePgcirkEwF2cjE3DxfhxUB43HK48bdRyjQeFCD1W3KjSkUW3JxlcAStZgFATLUACMMvBQFVVCCpWm5rR02Qvmga3qdEnt10pt2iGcgPBQOhHjz2gVKAx8liEDBHUJ0m5FogxZ2sAAGCRQTMpCLCaq%252BAVe%252FAlDW7Bi5hgwS3ZzTBpQ4a3dJNggggqcyhjxhrru1JmMLCB4CMrCsyiLEWMtDfqyKwqjZrYCqSChT1I0WkPIIME35iUjDFwgOwLC9LPJXT9ayyBDynC3tTbhaOYZrISELDhYsEA31kK8VfJGwi3D1RoV9krh1kD78x7DcEadZ9h5cl84YECEWf9oNvUQyYFidHPFBSWh9p8YF7EHIVEcWlAIAReGIYJ11FV33SbiGcTAAwBIiJmEDLhYw0JiDMRIdx%252FpYGGIUyxlRoqUfNJAfDwCIMJ1JR5gjwgyhKaSVk6qeBhA2pgR2BNKVSWDBRDMVCQcxk2R31470NKAjzwegGSSJOwhXooGvfkiDXAG8RgTyCGn1HvoVXPRl2JM8GcPD9g3g3AWMLfhfwc0wKZYhc4gIzx5SQpWik4GxQRfacGJpSDOASpfKN0oIEEGDYhq5JqPHiAhnNIsNgOsuZQmISOlcWnbM7JqFxiRPQCrKhw9FWQmi4Ce0Ooc4nVkkIy0miKjOq%252Bw8wP%252FF%252By1N0WUNQ777KwA%252FDMBKIAasGw%252BjrQYD43qxlOaVpOxp2uoc0XrrUH5NYFDQYRkIACg546QKp3xwCrsGxnUxeszaIZh773uApDfjjQ8IEUa3jnwHVgBHzmRe9LykDA85M11sJiLQkzpZPmSiYYCCBQSQcrxdNzoVVeacsNcNIeRL37%252BldezyivPsIURBUlcLapBG9SxCj3otcxlFJvSU3JDB5s10e7GVRUq7S3nwMm6dIyHdlULjQavEm89YytXI5LBoFyHGAs5SUABxWKFSEC30x1TCEncZ%252FSExGLQEP7GnYf%252BPQXj3u6NhuMqgXPtEAlx8pfUjHa83oxBUS6L%252FwVI19Cl6INsGQ27ZiT95ROu6coIBRcRgjocR0ihJRSOISHAxmUHfMd9OnCJ%252BlMAQNCWh7c7BAbMCtHbhPS5ODbQaVIg7Vhi1isw9xUT%252FKAYaG4jI5sSenPyTBANUB%252BH58iqkZcMkZixMwJJzKg85Ew0WI0MrgsI8OCgk48AJ38vs8ommAJAMMxiC%252FLawRPCkZBQaKIjGZgANzq
<link href="data:text/css;charset=utf-8,%0A%2Elayout%20div%2C%20%23footer%20%2A%2C%20%23controlForm%20%2A%20%7Bdisplay%3A%20none%3B%7D%0A%23footer%2C%20%23controls%2C%20%23controlForm%2C%20%23navLinks%2C%20%23toggle%20%7B%0Adisplay%3A%20block%3B%20visibility%3A%20visible%3B%20margin%3A%200%3B%20padding%3A%200%3B%7D%0A%23toggle%20%7Bfloat%3A%20right%3B%20padding%3A%200%2E5em%3B%7D%0Ahtml%3Ebody%20%23toggle%20%7Bposition%3A%20fixed%3B%20top%3A%200%3B%20right%3A%200%3B%7D%0A%0A%23slide0%20h1%2C%20%23slide0%20h2%2C%20%23slide0%20h3%2C%20%23slide0%20h4%20%7Bborder%3A%20none%3B%20margin%3A%200%3B%7D%0A%23slide0%20h1%20%7Bpadding%2Dtop%3A%201%2E5em%3B%7D%0A%2Eslide%20h1%20%7Bmargin%3A%201%2E5em%200%200%3B%20padding%2Dtop%3A%200%2E25em%3B%0Aborder%2Dtop%3A%201px%20solid%20%23888%3B%20border%2Dbottom%3A%201px%20solid%20%23AAA%3B%7D%0A%23toggle%20%7Bborder%3A%201px%20solid%3B%20border%2Dwidth%3A%200%200%201px%201px%3B%20background%3A%20%23FFF%3B%7D%0A" rel="stylesheet" type="text/css" media="screen" id="outlineStyle" />
<link href="data:text/css;charset=utf-8,%0A%2Eslide%2C%20ul%20%7Bpage%2Dbreak%2Dinside%3A%20avoid%3B%20visibility%3A%20visible%20%21important%3B%7D%0Ah1%20%7Bpage%2Dbreak%2Dafter%3A%20avoid%3B%7D%0Abody%20%7Bfont%2Dsize%3A%2012pt%3B%20background%3A%20white%3B%7D%0A%2A%20%7Bcolor%3A%20black%3B%7D%0A%23slide0%20h1%20%7Bfont%2Dsize%3A%20200%25%3B%20border%3A%20none%3B%20margin%3A%200%2E5em%200%200%2E25em%3B%7D%0A%23slide0%20h3%20%7Bmargin%3A%200%3B%20padding%3A%200%3B%7D%0A%23slide0%20h4%20%7Bmargin%3A%200%200%200%2E5em%3B%20padding%3A%200%3B%7D%0A%23slide0%20%7Bmargin%2Dbottom%3A%203em%3B%7D%0Ah1%20%7Bborder%2Dtop%3A%202pt%20solid%20gray%3B%20border%2Dbottom%3A%201px%20dotted%20silver%3B%7D%0A%2Eextra%20%7Bbackground%3A%20transparent%20%21important%3B%7D%0Adiv%2Eextra%2C%20pre%2Eextra%2C%20%2Eexample%20%7Bfont%2Dsize%3A%2010pt%3B%20color%3A%20%23333%3B%7D%0Aul%2Eextra%20a%20%7Bfont%2Dweight%3A%20bold%3B%7D%0Ap%2Eexample%20%7Bdisplay%3A%20none%3B%7D%0A%23header%20%7Bdisplay%3A%20none%3B%7D%0A%23footer%20h1%20%7Bmargin%3A%200%3B%20border%2Dbottom%3A%201px%20solid%3B%20color%3A%20gray%3B%20font%2Dstyle%3A%20italic%3B%7D%0A%23footer%20h2%2C%20%23controls%20%7Bdisplay%3A%20none%3B%7D%0A%0A%2Elayout%2C%20%2Elayout%20%2A%20%7Bdisplay%3A%20none%20%21important%3B%7D" rel="stylesheet" type="text/css" media="print" id="slidePrint" />
<link href="data:text/css;charset=utf-8,%0A%2Eslide%20%7B%0Avisibility%3A%20visible%20%21important%3B%0Aposition%3A%20static%20%21important%3B%0Apage%2Dbreak%2Dbefore%3A%20always%3B%0A%7D%0A%23slide0%20%7Bpage%2Dbreak%2Dbefore%3A%20avoid%3B%7D%0A" rel="stylesheet" type="text/css" media="projection" id="operaFix" />
2014-12-24 11:58:51 +03:00
<!-- S5 JS -->
2016-09-17 10:01:05 +03:00
<script src="data:application/x-javascript;base64,Ly8gUzUgdjEuMSBzbGlkZXMuanMgLS0gcmVsZWFzZWQgaW50byB0aGUgUHVibGljIERvbWFpbgovLwovLyBQbGVhc2Ugc2VlIGh0dHA6Ly93d3cubWV5ZXJ3ZWIuY29tL2VyaWMvdG9vbHMvczUvY3JlZGl0cy5odG1sIGZvciBpbmZvcm1hdGlvbiAKLy8gYWJvdXQgYWxsIHRoZSB3b25kZXJmdWwgYW5kIHRhbGVudGVkIGNvbnRyaWJ1dG9ycyB0byB0aGlzIGNvZGUhCgp2YXIgdW5kZWY7CnZhciBzbGlkZUNTUyA9ICcnOwp2YXIgc251bSA9IDA7CnZhciBzbWF4ID0gMTsKdmFyIGluY3BvcyA9IDA7CnZhciBudW1iZXIgPSB1bmRlZjsKdmFyIHM1bW9kZSA9IHRydWU7CnZhciBkZWZhdWx0VmlldyA9ICdzbGlkZXNob3cnOwp2YXIgY29udHJvbFZpcyA9ICd2aXNpYmxlJzsKCnZhciBpc0lFID0gbmF2aWdhdG9yLmFwcE5hbWUgPT0gJ01pY3Jvc29mdCBJbnRlcm5ldCBFeHBsb3JlcicgPyAxIDogMDsKdmFyIGlzT3AgPSBuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoJ09wZXJhJykgPiAtMSA/IDEgOiAwOwp2YXIgaXNHZSA9IG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignR2Vja28nKSA+IC0xICYmIG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignU2FmYXJpJykgPCAxID8gMSA6IDA7CgpmdW5jdGlvbiBoYXNDbGFzcyhvYmplY3QsIGNsYXNzTmFtZSkgewoJaWYgKCFvYmplY3QuY2xhc3NOYW1lKSByZXR1cm4gZmFsc2U7CglyZXR1cm4gKG9iamVjdC5jbGFzc05hbWUuc2VhcmNoKCcoXnxcXHMpJyArIGNsYXNzTmFtZSArICcoXFxzfCQpJykgIT0gLTEpOwp9CgpmdW5jdGlvbiBoYXNWYWx1ZShvYmplY3QsIHZhbHVlKSB7CglpZiAoIW9iamVjdCkgcmV0dXJuIGZhbHNlOwoJcmV0dXJuIChvYmplY3Quc2VhcmNoKCcoXnxcXHMpJyArIHZhbHVlICsgJyhcXHN8JCknKSAhPSAtMSk7Cn0KCmZ1bmN0aW9uIHJlbW92ZUNsYXNzKG9iamVjdCxjbGFzc05hbWUpIHsKCWlmICghb2JqZWN0KSByZXR1cm47CglvYmplY3QuY2xhc3NOYW1lID0gb2JqZWN0LmNsYXNzTmFtZS5yZXBsYWNlKG5ldyBSZWdFeHAoJyhefFxccyknK2NsYXNzTmFtZSsnKFxcc3wkKScpLCBSZWdFeHAuJDErUmVnRXhwLiQyKTsKfQoKZnVuY3Rpb24gYWRkQ2xhc3Mob2JqZWN0LGNsYXNzTmFtZSkgewoJaWYgKCFvYmplY3QgfHwgaGFzQ2xhc3Mob2JqZWN0LCBjbGFzc05hbWUpKSByZXR1cm47CglpZiAob2JqZWN0LmNsYXNzTmFtZSkgewoJCW9iamVjdC5jbGFzc05hbWUgKz0gJyAnK2NsYXNzTmFtZTsKCX0gZWxzZSB7CgkJb2JqZWN0LmNsYXNzTmFtZSA9IGNsYXNzTmFtZTsKCX0KfQoKZnVuY3Rpb24gR2V0RWxlbWVudHNXaXRoQ2xhc3NOYW1lKGVsZW1lbnROYW1lLGNsYXNzTmFtZSkgewoJdmFyIGFsbEVsZW1lbnRzID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoZWxlbWVudE5hbWUpOwoJdmFyIGVsZW1Db2xsID0gbmV3IEFycmF5KCk7Cglmb3IgKHZhciBpID0gMDsgaTwgYWxsRWxlbWVudHMubGVuZ3RoOyBpKyspIHsKCQlpZiAoaGFzQ2xhc3MoYWxsRWxlbWVudHNbaV0sIGNsYXNzTmFtZSkpIHsKCQkJZWxlbUNvbGxbZWxlbUNvbGwubGVuZ3RoXSA9IGFsbEVsZW1lbnRzW2ldOwoJCX0KCX0KCXJldHVybiBlbGVtQ29sbDsKfQoKZnVuY3Rpb24gaXNQYXJlbnRPclNlbGYoZWxlbWVudCwgaWQpIHsKCWlmIChlbGVtZW50ID09IG51bGwgfHwgZWxlbWVudC5ub2RlTmFtZT09J0JPRFknKSByZXR1cm4gZmFsc2U7CgllbHNlIGlmIChlbGVtZW50LmlkID09IGlkKSByZXR1cm4gdHJ1ZTsKCWVsc2UgcmV0dXJuIGlzUGFyZW50T3JTZWxmKGVsZW1lbnQucGFyZW50Tm9kZSwgaWQpOwp9CgpmdW5jdGlvbiBub2RlVmFsdWUobm9kZSkgewoJdmFyIHJlc3VsdCA9ICIiOwoJaWYgKG5vZGUubm9kZVR5cGUgPT0gMSkgewoJCXZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGROb2RlczsKCQlmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgKytpKSB7CgkJCXJlc3VsdCArPSBub2RlVmFsdWUoY2hpbGRyZW5baV0pOwoJCX0JCQoJfQoJZWxzZSBpZiAobm9kZS5ub2RlVHlwZSA9PSAzKSB7CgkJcmVzdWx0ID0gbm9kZS5ub2RlVmFsdWU7Cgl9CglyZXR1cm4ocmVzdWx0KTsKfQoKZnVuY3Rpb24gc2xpZGVMYWJlbCgpIHsKCXZhciBzbGlkZUNvbGwgPSBHZXRFbGVtZW50c1dpdGhDbGFzc05hbWUoJyonLCdzbGlkZScpOwoJdmFyIGxpc3QgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnanVtcGxpc3QnKTsKCXNtYXggPSBzbGlkZUNvbGwubGVuZ3RoOwoJZm9yICh2YXIgbiA9IDA7IG4gPCBzbWF4OyBuKyspIHsKCQl2YXIgb2JqID0gc2xpZGVDb2xsW25dOwoKCQl2YXIgZGlkID0gJ3NsaWRlJyArIG4udG9TdHJpbmcoKTsKCQlvYmouc2V0QXR0cmlidXRlKCdpZCcsZGlkKTsKCQlpZiAoaXNPcCkgY29udGludWU7CgoJCXZhciBvdGV4dCA9ICcnOwoJCXZhciBtZW51ID0gb2JqLmZpcnN0Q2hpbGQ7CgkJaWYgKCFtZW51KSBjb250aW51ZTsgLy8gdG8gY29wZSB3aXRoIGVtcHR5IHNsaWRlcwoJCXdoaWxlIChtZW51ICYmIG1lbnUubm9kZVR5cGUgPT0gMykgewoJCQltZW51ID0gbWVudS5uZXh0U2libGluZzsKCQl9CgkgCWlmICghbWVudSkgY29udGludWU7IC8vIHRvIGNvcGUgd2l0aCBzbGlkZXMgd2l0aCBvbmx5IHRleHQgbm9kZXMKCgkJdmFyIG1lbnVub2RlcyA9IG1lbnUuY2hpbGROb2RlczsKCQlmb3IgKHZhciBvID0gMDsgbyA8IG1lbnVub2Rlcy5sZW5ndGg7IG8rKykgewoJCQlvdGV4dCArPSBub2RlVmFsdWUobWVudW5vZGVzW29dKTsKCQl9CgkJbGlzdC5vcHRpb25zW2xpc3QubGVuZ3RoXSA9IG5ldyBPcHRpb24obiArICcgOiAnICArIG90ZXh0LCBuKTsKCX0KfQoKZnVuY3Rpb24gY3VycmVudFNsaWRlKCkgewoJdmFyIGNzOwoJaWYgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKSB7CgkJY3MgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnY3VycmVudFNsaWRlJyk7Cgl9IGVsc2UgewoJCWNzID0gZG9jdW1lbnQuY3VycmVudFNsaWRlOwoJfQoJY3MuaW5uZXJIVE1MID0gJzxzcGFuIGlkPSJjc0hlcmUiPicgKyBzbnVtICsgJzxcL3NwYW4
<script src="data:application/x-javascript;base64,LyoNCkxhVGVYTWF0aE1MLmpzDQo9PT09PT09PT09PT09PQ0KDQpUaGlzIGZpbGUsIGluIHRoaXMgZm9ybSwgaXMgZHVlIHRvIERvdWdsYXMgV29vZGFsbCwgSnVuZSAyMDA2Lg0KSXQgY29udGFpbnMgSmF2YVNjcmlwdCBmdW5jdGlvbnMgdG8gY29udmVydCAobW9zdCBzaW1wbGUpIExhVGVYDQptYXRoIG5vdGF0aW9uIHRvIFByZXNlbnRhdGlvbiBNYXRoTUwuICBJdCB3YXMgb2J0YWluZWQgYnkNCmRvd25sb2FkaW5nIHRoZSBmaWxlIEFTQ0lJTWF0aE1MLmpzIGZyb20NCglodHRwOi8vd3d3MS5jaGFwbWFuLmVkdS9+amlwc2VuL21hdGhtbC9hc2NpaW1hdGhkb3dubG9hZC8NCmFuZCBtb2RpZnlpbmcgaXQgc28gdGhhdCBpdCBjYXJyaWVzIG91dCBPTkxZIHRob3NlIGNvbnZlcnNpb25zDQp0aGF0IHdvdWxkIGJlIGNhcnJpZWQgb3V0IGluIExhVGVYLiAgQSBkZXNjcmlwdGlvbiBvZiB0aGUgb3JpZ2luYWwNCmZpbGUsIHdpdGggZXhhbXBsZXMsIGNhbiBiZSBmb3VuZCBhdA0KCXd3dzEuY2hhcG1hbi5lZHUvfmppcHNlbi9tYXRobWwvYXNjaWltYXRoLmh0bWwNCglBU0NJSU1hdGhNTDogTWF0aCBvbiB0aGUgd2ViIGZvciBldmVyeW9uZQ0KDQpIZXJlIGlzIHRoZSBoZWFkZXIgbm90aWNlIGZyb20gdGhlIG9yaWdpbmFsIGZpbGU6DQoNCkFTQ0lJTWF0aE1MLmpzDQo9PT09PT09PT09PT09PQ0KVGhpcyBmaWxlIGNvbnRhaW5zIEphdmFTY3JpcHQgZnVuY3Rpb25zIHRvIGNvbnZlcnQgQVNDSUkgbWF0aCBub3RhdGlvbg0KdG8gUHJlc2VudGF0aW9uIE1hdGhNTC4gVGhlIGNvbnZlcnNpb24gaXMgZG9uZSB3aGlsZSB0aGUgKFgpSFRNTCBwYWdlDQpsb2FkcywgYW5kIHNob3VsZCB3b3JrIHdpdGggRmlyZWZveC9Nb3ppbGxhL05ldHNjYXBlIDcrIGFuZCBJbnRlcm5ldA0KRXhwbG9yZXIgNitNYXRoUGxheWVyIChodHRwOi8vd3d3LmRlc3NjaS5jb20vZW4vcHJvZHVjdHMvbWF0aHBsYXllci8pLg0KSnVzdCBhZGQgdGhlIG5leHQgbGluZSB0byB5b3VyIChYKUhUTUwgcGFnZSB3aXRoIHRoaXMgZmlsZSBpbiB0aGUgc2FtZSBmb2xkZXI6DQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJBU0NJSU1hdGhNTC5qcyI+PC9zY3JpcHQ+DQpUaGlzIGlzIGEgY29udmVuaWVudCBhbmQgaW5leHBlbnNpdmUgc29sdXRpb24gZm9yIGF1dGhvcmluZyBNYXRoTUwuDQoNClZlcnNpb24gMS40LjcgRGVjIDE1LCAyMDA1LCAoYykgUGV0ZXIgSmlwc2VuIGh0dHA6Ly93d3cuY2hhcG1hbi5lZHUvfmppcHNlbg0KTGF0ZXN0IHZlcnNpb24gYXQgaHR0cDovL3d3dy5jaGFwbWFuLmVkdS9+amlwc2VuL21hdGhtbC9BU0NJSU1hdGhNTC5qcw0KRm9yIGNoYW5nZXMgc2VlIGh0dHA6Ly93d3cuY2hhcG1hbi5lZHUvfmppcHNlbi9tYXRobWwvYXNjaWltYXRoY2hhbmdlcy50eHQNCklmIHlvdSB1c2UgaXQgb24gYSB3ZWJwYWdlLCBwbGVhc2Ugc2VuZCB0aGUgVVJMIHRvIGppcHNlbkBjaGFwbWFuLmVkdQ0KDQpUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeQ0KaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkNCnRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDIgb2YgdGhlIExpY2Vuc2UsIG9yIChhdA0KeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLg0KDQpUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwNCmJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mDQpNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VDQpHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIChhdCBodHRwOi8vd3d3LmdudS5vcmcvY29weWxlZnQvZ3BsLmh0bWwpDQpmb3IgbW9yZSBkZXRhaWxzLg0KDQpMYVRlWE1hdGhNTC5qcyAoY3RkKQ0KPT09PT09PT09PT09PT0NCg0KVGhlIGluc3RydWN0aW9ucyBmb3IgdXNlIGFyZSB0aGUgc2FtZSBhcyBmb3IgdGhlIG9yaWdpbmFsDQpBU0NJSU1hdGhNTC5qcywgZXhjZXB0IHRoYXQgb2YgY291cnNlIHRoZSBsaW5lIHlvdSBhZGQgdG8geW91cg0KZmlsZSBzaG91bGQgYmUNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9IkxhVGVYTWF0aE1MLmpzIj48L3NjcmlwdD4NCk9yIHVzZSBhYnNvbHV0ZSBwYXRoIG5hbWVzIGlmIHRoZSBmaWxlIGlzIG5vdCBpbiB0aGUgc2FtZSBmb2xkZXINCmFzIHlvdXIgKFgpSFRNTCBwYWdlLg0KKi8NCg0KdmFyIGNoZWNrRm9yTWF0aE1MID0gdHJ1ZTsgICAvLyBjaGVjayBpZiBicm93c2VyIGNhbiBkaXNwbGF5IE1hdGhNTA0KdmFyIG5vdGlmeUlmTm9NYXRoTUwgPSB0cnVlOyAvLyBkaXNwbGF5IG5vdGUgaWYgbm8gTWF0aE1MIGNhcGFiaWxpdHkNCnZhciBhbGVydElmTm9NYXRoTUwgPSBmYWxzZTsgIC8vIHNob3cgYWxlcnQgYm94IGlmIG5vIE1hdGhNTCBjYXBhYmlsaXR5DQovLyB3YXMgInJlZCI6DQp2YXIgbWF0aGNvbG9yID0gIiI7CSAgICAgLy8gY2hhbmdlIGl0IHRvICIiICh0byBpbmhlcml0KSBvciBhbnkgb3RoZXIgY29sb3INCi8vIHdhcyAic2VyaWYiOg0KdmFyIG1hdGhmb250ZmFtaWx5ID0gIiI7ICAgICAgLy8gY2hhbmdlIHRvICIiIHRvIGluaGVyaXQgKHdvcmtzIGluIElFKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3IgYW5vdGhlciBmYW1pbHkgKGUuZy4gImFyaWFsIikNCnZhciBzaG93YXNjaWlmb3JtdWxhb25ob3ZlciA9IHRydWU7IC8vIGhlbHBzIHN0dWRlbnRzIGxlYXJuIEFTQ0lJTWF0aA0KLyoNCi8vIENvbW1lbnRlZCBvdXQgYnkgRFJXIC0tIG5vdCBub3cgdXNlZCAtLSBzZWUgREVMSU1JVEVSUyAodHdpY2UpIG5lYXIgdGhlIGVuZA0KdmFyIGRpc3BsYXlzdHlsZSA9IGZhbHNlOyAgICAgLy8gcHV0cyBsaW1pdHMgYWJvdmUgYW5kIGJlbG93IGxhcmdlIG9wZXJhdG9ycw0
2014-12-24 11:58:51 +03:00
</head>
<body>
<div class="layout">
<div id="controls"></div>
<div id="currentSlide"></div>
<div id="header"></div>
<div id="footer">
<h1>Kei Hibino</h1>
2014-12-24 13:45:21 +03:00
<h2>Haskell Relational Record's Query-Building DSL</h2>
2014-12-24 11:58:51 +03:00
</div>
</div>
<div class="presentation">
<div class="titleslide slide">
2016-09-17 10:01:05 +03:00
<h1 class="title">Haskell Relational Record's Query-Building DSL</h1>
<h3 class="author">2014-12-25 (Updated 2014-12-29)</h3>
<h4 class="date">Kei Hibino</h4>
2014-12-24 11:58:51 +03:00
</div>
2014-12-24 13:45:21 +03:00
<div id="rough-design" class="titleslide slide section level1"><h1>Rough Design</h1></div><div id="query-dsl-basics" class="slide section level2">
2014-12-24 11:58:51 +03:00
<h1>Query DSL Basics</h1>
<p><span class="LaTeX">$$\{ (x, y) | x \in X, y \in Y, \pi_1(x) = \pi_2(y) \}$$</span></p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell">[ (x, y) <span class="fu">|</span> x <span class="ot">&lt;-</span> xs, y <span class="ot">&lt;-</span> ys, fst x <span class="fu">==</span> snd y ] <span class="co">-- Comprehension</span>
2014-12-24 11:58:51 +03:00
2016-09-17 10:01:05 +03:00
<span class="kw">do</span> { x <span class="ot">&lt;-</span> xs; y <span class="ot">&lt;-</span> ys; guard (fst x <span class="fu">==</span> snd y); return (x, y) } <span class="co">-- List Monad</span></code></pre></div>
2014-12-24 13:45:21 +03:00
<p>Building a joined query like list comprehension or list Monad:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">personAndBirthday ::</span> <span class="dt">Relation</span> () (<span class="dt">Person</span>, <span class="dt">Birthday</span>)
2014-12-24 11:58:51 +03:00
personAndBirthday <span class="fu">=</span> relation <span class="fu">$</span> <span class="kw">do</span>
p <span class="ot">&lt;-</span> query person <span class="co">-- Join product accumulated</span>
b <span class="ot">&lt;-</span> query birthday
on <span class="fu">$</span> p <span class="fu">!</span> Person.name' <span class="fu">.=.</span> b <span class="fu">!</span> Birthday.name'
2016-09-17 10:01:05 +03:00
return <span class="fu">$</span> p <span class="fu">&gt;&lt;</span> b</code></pre></div>
2014-12-25 03:12:12 +03:00
</div><div id="typing" class="slide section level2">
<h1>Typing</h1>
2014-12-24 13:45:21 +03:00
<p>A simple and useful method:</p>
2014-12-24 11:58:51 +03:00
<ul>
2014-12-25 03:12:12 +03:00
<li>Untype and accumulate from typeful DSL terms into a state monad context</li>
2014-12-24 11:58:51 +03:00
<li>Typeful result</li>
2014-12-25 03:12:12 +03:00
<li>Phantom context and result type</li>
2014-12-24 11:58:51 +03:00
</ul>
2014-12-25 03:12:12 +03:00
</div><div id="state-stack" class="slide section level2">
2014-12-24 11:58:51 +03:00
<h1>State Stack</h1>
2014-12-24 13:45:21 +03:00
<p>Haskell Relational Record's query-building DSL accumulates various context in a state monad context stack.</p>
2014-12-24 11:58:51 +03:00
<ul>
<li>Join product</li>
<li>Aggregate terms</li>
<li>Ordering terms</li>
<li>Restrict predicates</li>
</ul>
</div>
<div id="contexts-in-state" class="titleslide slide section level1"><h1>Contexts in State</h1></div><div id="join-product" class="slide section level2">
2014-12-24 13:45:21 +03:00
<h1>Join Product</h1>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">query ::</span> (<span class="dt">MonadQualify</span> <span class="dt">ConfigureQuery</span> m, <span class="dt">MonadQuery</span> m)
2014-12-24 11:58:51 +03:00
<span class="ot">=&gt;</span> <span class="dt">Relation</span> () r
<span class="ot">-&gt;</span> m (<span class="dt">Projection</span> <span class="dt">Flat</span> r)
<span class="co">-- Used for outer join</span>
<span class="ot">queryMaybe ::</span> (<span class="dt">MonadQualify</span> <span class="dt">ConfigureQuery</span> m, <span class="dt">MonadQuery</span> m)
2014-12-24 11:58:51 +03:00
<span class="ot">=&gt;</span> <span class="dt">Relation</span> () r
<span class="ot">-&gt;</span> m (<span class="dt">Projection</span> <span class="dt">Flat</span> (<span class="dt">Maybe</span> r))
2016-09-17 10:01:05 +03:00
<span class="ot">on ::</span> <span class="dt">MonadQuery</span> m <span class="ot">=&gt;</span> <span class="dt">Projection</span> <span class="dt">Flat</span> (<span class="dt">Maybe</span> <span class="dt">Bool</span>) <span class="ot">-&gt;</span> m ()</code></pre></div>
2015-04-06 18:14:17 +03:00
<p>'query' and 'queryMaybe' return a Projection type of table form results.</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> .. <span class="kw">FROM</span> ...
2014-12-24 11:58:51 +03:00
<span class="co">-- Accumulating uniquely qualified</span>
<span class="co">-- ( like 'as T0', 'as T1' ... )</span>
2016-09-17 10:01:05 +03:00
<span class="co">-- table forms of SQL FROM clause</span></code></pre></div>
2014-12-24 11:58:51 +03:00
</div><div id="join-example" class="slide section level2">
<h1>Join Example</h1>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">personAndBirthdayL ::</span> <span class="dt">Relation</span> () (<span class="dt">Person</span>, <span class="dt">Maybe</span> <span class="dt">Birthday</span>)
2014-12-24 11:58:51 +03:00
personAndBirthdayL <span class="fu">=</span> relation <span class="fu">$</span> <span class="kw">do</span>
p <span class="ot">&lt;-</span> query person
b <span class="ot">&lt;-</span> queryMaybe birthday
on <span class="fu">$</span> just (p <span class="fu">!</span> Person.name') <span class="fu">.=.</span> b <span class="fu">?!</span> Birthday.name'
2016-09-17 10:01:05 +03:00
return <span class="fu">$</span> p <span class="fu">&gt;&lt;</span> b</code></pre></div>
2014-12-24 13:45:21 +03:00
<p>generates left-joined SQL:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> <span class="kw">ALL</span> T0.name <span class="kw">AS</span> f0, T0.age <span class="kw">AS</span> f1, T0.address <span class="kw">AS</span> f2,
2014-12-24 11:58:51 +03:00
T1.name <span class="kw">AS</span> f3, T1.day <span class="kw">AS</span> f4
<span class="kw">FROM</span> PUBLIC.person T0 <span class="kw">LEFT</span> <span class="kw">JOIN</span>
PUBLIC.birthday T1
2016-09-17 10:01:05 +03:00
<span class="kw">ON</span> (T0.name = T1.name)</code></pre></div>
2014-12-24 11:58:51 +03:00
</div><div id="aggregation" class="slide section level2">
<h1>Aggregation</h1>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">groupBy ::</span> <span class="dt">MonadAggregate</span> m
2014-12-24 11:58:51 +03:00
<span class="ot">=&gt;</span> <span class="dt">Projection</span> <span class="dt">Flat</span> r
<span class="co">-- ^ Projection to add into group by</span>
<span class="ot">-&gt;</span> m (<span class="dt">Projection</span> <span class="dt">Aggregated</span> r)
<span class="co">-- ^ Result context and aggregated projection</span>
<span class="ot">count ::</span> <span class="dt">Projection</span> <span class="dt">Flat</span> a <span class="ot">-&gt;</span> <span class="dt">Projection</span> <span class="dt">Aggregated</span> <span class="dt">Int64</span>
<span class="ot">max' ::</span> <span class="dt">Ord</span> a
2016-09-17 10:01:05 +03:00
<span class="ot">=&gt;</span> <span class="dt">Projection</span> <span class="dt">Flat</span> a <span class="ot">-&gt;</span> <span class="dt">Projection</span> <span class="dt">Aggregated</span> (<span class="dt">Maybe</span> a)</code></pre></div>
<p>'groupBy' can be used under only 'MonadAggregate' monad constraint, narrower than 'MonadQuery'.</p>
2014-12-24 13:45:21 +03:00
<p>'groupBy' returns a Projection value with an Aggregated context type:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> .. <span class="kw">GROUP</span> <span class="kw">BY</span> ...
2014-12-24 11:58:51 +03:00
<span class="co">-- Accumulating keys</span>
2016-09-17 10:01:05 +03:00
<span class="co">-- of SQL GROUP BY clause</span></code></pre></div>
2014-12-24 11:58:51 +03:00
</div><div id="aggregation-example" class="slide section level2">
<h1>Aggregation Example</h1>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">agesOfFamilies ::</span> <span class="dt">Relation</span> () (<span class="dt">String</span>, <span class="dt">Maybe</span> <span class="dt">Int32</span>)
2014-12-24 11:58:51 +03:00
agesOfFamilies <span class="fu">=</span> aggregateRelation <span class="fu">$</span> <span class="kw">do</span>
my <span class="ot">&lt;-</span> query myTable
gFam <span class="ot">&lt;-</span> groupBy <span class="fu">$</span> my <span class="fu">!</span> family' <span class="co">-- Specify grouping key</span>
2014-12-25 03:42:21 +03:00
2016-09-17 10:01:05 +03:00
return <span class="fu">$</span> gFam <span class="fu">&gt;&lt;</span> sum' (my <span class="fu">!</span> age') <span class="co">-- Aggregated results</span></code></pre></div>
2014-12-24 13:45:21 +03:00
<p>sums ages per family.</p>
<p>Generated SQL:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> <span class="kw">ALL</span> T0.family <span class="kw">AS</span> f0, <span class="fu">SUM</span> (T0.age) <span class="kw">AS</span> f1
2014-12-24 11:58:51 +03:00
<span class="kw">FROM</span> PUBLIC.my_table T0
2016-09-17 10:01:05 +03:00
<span class="kw">GROUP</span> <span class="kw">BY</span> T0.family</code></pre></div>
2014-12-24 13:45:21 +03:00
</div><div id="restrict" class="slide section level2">
<h1>Restrict</h1>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">restrict ::</span> <span class="dt">MonadRestrict</span> c m
2014-12-24 11:58:51 +03:00
<span class="ot">=&gt;</span> <span class="dt">Projection</span> c (<span class="dt">Maybe</span> <span class="dt">Bool</span>)
<span class="ot">-&gt;</span> m ()
<span class="ot">wheres ::</span> <span class="dt">MonadRestrict</span> <span class="dt">Flat</span> m
<span class="ot">=&gt;</span> <span class="dt">Projection</span> <span class="dt">Flat</span> (<span class="dt">Maybe</span> <span class="dt">Bool</span>)
2016-09-17 10:01:05 +03:00
<span class="ot">-&gt;</span> m ()</code></pre></div>
2014-12-24 13:45:21 +03:00
<p>adds a WHERE clause restriction:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> .. <span class="kw">WHERE</span> x <span class="kw">AND</span> y <span class="kw">AND</span> ...
2014-12-24 11:58:51 +03:00
<span class="co">-- Accumulating AND predicates</span>
2016-09-17 10:01:05 +03:00
<span class="co">-- of SQL WHERE clause</span></code></pre></div>
2014-12-24 13:45:21 +03:00
</div><div id="restrict-1" class="slide section level2">
<h1>Restrict</h1>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">restrict ::</span> <span class="dt">MonadRestrict</span> c m
2014-12-24 11:58:51 +03:00
<span class="ot">=&gt;</span> <span class="dt">Projection</span> c (<span class="dt">Maybe</span> <span class="dt">Bool</span>)
<span class="ot">-&gt;</span> m ()
<span class="ot">having ::</span> <span class="dt">MonadRestrict</span> <span class="dt">Aggregated</span> m
<span class="ot">=&gt;</span> <span class="dt">Projection</span> <span class="dt">Aggregated</span> (<span class="dt">Maybe</span> <span class="dt">Bool</span>)
2016-09-17 10:01:05 +03:00
<span class="ot">-&gt;</span> m ()</code></pre></div>
2014-12-24 13:45:21 +03:00
<p>adds a HAVING clause restriction, in which only Projection type values with aggregated context are allowed:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> .. <span class="kw">HAVING</span> x <span class="kw">AND</span> y <span class="kw">AND</span> ...
2014-12-24 11:58:51 +03:00
<span class="co">-- Accumulating AND predicates</span>
2016-09-17 10:01:05 +03:00
<span class="co">-- of SQL HAVING clause</span></code></pre></div>
2014-12-24 13:45:21 +03:00
</div><div id="restrict-example" class="slide section level2">
<h1>Restrict Example</h1>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">sameBirthdayHeisei' ::</span> <span class="dt">Relation</span> () (<span class="dt">Day</span>, <span class="dt">Int64</span>)
2014-12-24 11:58:51 +03:00
sameBirthdayHeisei' <span class="fu">=</span> aggregateRelation <span class="fu">$</span> <span class="kw">do</span>
p <span class="ot">&lt;-</span> query person
b <span class="ot">&lt;-</span> query birthday
on <span class="fu">$</span> p <span class="fu">!</span> Person.name' <span class="fu">.=.</span> b <span class="fu">!</span> Birthday.name'
wheres <span class="fu">$</span> b <span class="fu">!</span> Birthday.day' <span class="fu">.&gt;=.</span> value (fromGregorian <span class="dv">1989</span> <span class="dv">1</span> <span class="dv">8</span>)
gbd <span class="ot">&lt;-</span> groupBy <span class="fu">$</span> b <span class="fu">!</span> Birthday.day'
having <span class="fu">$</span> count (p <span class="fu">!</span> Person.name') <span class="fu">.&gt;.</span> value <span class="dv">1</span>
2016-09-17 10:01:05 +03:00
return <span class="fu">$</span> gbd <span class="fu">&gt;&lt;</span> count (p <span class="fu">!</span> Person.name')</code></pre></div>
2014-12-24 13:45:21 +03:00
<p>counts people with the same birthday, who were born in the Heisei period.</p>
<p>Generated SQL:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> <span class="kw">ALL</span> T1.day <span class="kw">AS</span> f0, <span class="fu">COUNT</span> (T0.name) <span class="kw">AS</span> f1
2014-12-24 11:58:51 +03:00
<span class="kw">FROM</span> PUBLIC.person T0 <span class="kw">INNER</span> <span class="kw">JOIN</span> PUBLIC.birthday T1
<span class="kw">ON</span> (T0.name = T1.name)
<span class="kw">WHERE</span> (T1.day &gt;= <span class="dt">DATE</span> <span class="st">'1989-01-08'</span>)
2016-09-17 10:01:05 +03:00
<span class="kw">GROUP</span> <span class="kw">BY</span> T1.day <span class="kw">HAVING</span> (<span class="fu">COUNT</span> (T0.name) &gt; <span class="dv">1</span>)</code></pre></div>
2014-12-24 13:45:21 +03:00
</div><div id="restrict-example-1" class="slide section level2">
<h1>Restrict Example</h1>
2014-12-25 04:22:33 +03:00
<p>Generated SQL:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> <span class="kw">ALL</span> T1.day <span class="kw">AS</span> f0, <span class="fu">COUNT</span> (T0.name) <span class="kw">AS</span> f1
2014-12-25 04:22:33 +03:00
<span class="kw">FROM</span> PUBLIC.person T0 <span class="kw">INNER</span> <span class="kw">JOIN</span> PUBLIC.birthday T1
<span class="kw">ON</span> (T0.name = T1.name)
<span class="kw">WHERE</span> (T1.day &gt;= <span class="dt">DATE</span> <span class="st">'1989-01-08'</span>)
2016-09-17 10:01:05 +03:00
<span class="kw">GROUP</span> <span class="kw">BY</span> T1.day <span class="kw">HAVING</span> (<span class="fu">COUNT</span> (T0.name) &gt; <span class="dv">1</span>)</code></pre></div>
2014-12-25 04:22:33 +03:00
</div><div id="restrict-example-2" class="slide section level2">
<h1>Restrict Example</h1>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">sameBirthdayHeisei ::</span> <span class="dt">Relation</span> () (<span class="dt">Day</span>, <span class="dt">Int64</span>)
2014-12-24 11:58:51 +03:00
sameBirthdayHeisei <span class="fu">=</span> aggregateRelation <span class="fu">$</span> <span class="kw">do</span>
p <span class="ot">&lt;-</span> query person
b <span class="ot">&lt;-</span> query birthday
on <span class="fu">$</span> p <span class="fu">!</span> Person.name' <span class="fu">.=.</span> b <span class="fu">!</span> Birthday.name'
<span class="kw">let</span> birthDay <span class="fu">=</span> b <span class="fu">!</span> Birthday.day'
wheres <span class="fu">$</span> birthDay <span class="fu">.&gt;=.</span> value (fromGregorian <span class="dv">1989</span> <span class="dv">1</span> <span class="dv">8</span>)
gbd <span class="ot">&lt;-</span> groupBy birthDay
<span class="kw">let</span> personCount <span class="fu">=</span> count <span class="fu">$</span> p <span class="fu">!</span> Person.name'
having <span class="fu">$</span> personCount <span class="fu">.&gt;.</span> value <span class="dv">1</span>
2016-09-17 10:01:05 +03:00
return <span class="fu">$</span> gbd <span class="fu">&gt;&lt;</span> personCount</code></pre></div>
2014-12-24 13:45:21 +03:00
<p>binds using let.</p>
2014-12-24 11:58:51 +03:00
</div><div id="ordering" class="slide section level2">
<h1>Ordering</h1>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">orderBy ::</span> <span class="dt">Monad</span> m
2014-12-24 11:58:51 +03:00
<span class="ot">=&gt;</span> <span class="dt">Projection</span> c t
<span class="co">-- ^ Ordering terms to add</span>
<span class="ot">-&gt;</span> <span class="dt">Order</span>
<span class="co">-- ^ Order direction -- Asc | Desc</span>
<span class="ot">-&gt;</span> <span class="dt">Orderings</span> c m ()
2016-09-17 10:01:05 +03:00
<span class="co">-- ^ Result context with ordering</span></code></pre></div>
2014-12-24 13:45:21 +03:00
<p>Only Projection type values with specified (Flat, Aggregated, ...) context are allowed.</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> .. <span class="kw">ORDER</span> <span class="kw">BY</span> ...
<span class="co">-- Accumulating terms of ORDER BY clause</span></code></pre></div>
2014-12-24 11:58:51 +03:00
</div><div id="ordering-example" class="slide section level2">
<h1>Ordering Example</h1>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">personAndBirthdayO ::</span> <span class="dt">Relation</span> () (<span class="dt">Person</span>, <span class="dt">Birthday</span>)
2014-12-24 11:58:51 +03:00
personAndBirthdayO <span class="fu">=</span> relation <span class="fu">$</span> <span class="kw">do</span>
p <span class="ot">&lt;-</span> query person
b <span class="ot">&lt;-</span> query birthday
on <span class="fu">$</span> p <span class="fu">!</span> Person.name' <span class="fu">.=.</span> b <span class="fu">!</span> Birthday.name'
orderBy (b <span class="fu">!</span> Birthday.day') <span class="dt">Asc</span> <span class="co">-- Specify ordering key</span>
orderBy (p <span class="fu">!</span> Person.name') <span class="dt">Asc</span>
2016-09-17 10:01:05 +03:00
return <span class="fu">$</span> p <span class="fu">&gt;&lt;</span> b</code></pre></div>
2014-12-24 13:45:21 +03:00
<p>orders by birthday and then name:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> <span class="kw">ALL</span> T0.name <span class="kw">AS</span> f0, T0.age <span class="kw">AS</span> f1, T0.address <span class="kw">AS</span> f2,
2014-12-24 11:58:51 +03:00
T1.name <span class="kw">AS</span> f3, T1.day <span class="kw">AS</span> f4
<span class="kw">FROM</span> PUBLIC.person T0 <span class="kw">INNER</span> <span class="kw">JOIN</span> PUBLIC.birthday T1
<span class="kw">ON</span> (T0.name = T1.name)
2016-09-17 10:01:05 +03:00
<span class="kw">ORDER</span> <span class="kw">BY</span> T1.day <span class="kw">ASC</span>, T0.name <span class="kw">ASC</span></code></pre></div>
2014-12-24 11:58:51 +03:00
</div><div id="ordering-example-1" class="slide section level2">
<h1>Ordering Example</h1>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">birthdayHeiseiDesc ::</span> <span class="dt">Relation</span> () (<span class="dt">Day</span>, <span class="dt">Int64</span>)
2014-12-24 11:58:51 +03:00
birthdayHeiseiDesc <span class="fu">=</span> aggregateRelation <span class="fu">$</span> <span class="kw">do</span>
p <span class="ot">&lt;-</span> query person
b <span class="ot">&lt;-</span> query birthday
on <span class="fu">$</span> p <span class="fu">!</span> Person.name' <span class="fu">.=.</span> b <span class="fu">!</span> Birthday.name'
<span class="kw">let</span> birthDay <span class="fu">=</span> b <span class="fu">!</span> Birthday.day'
wheres <span class="fu">$</span> birthDay <span class="fu">.&gt;=.</span> value (fromGregorian <span class="dv">1989</span> <span class="dv">1</span> <span class="dv">8</span>)
gbd <span class="ot">&lt;-</span> groupBy birthDay
<span class="kw">let</span> personCount <span class="fu">=</span> count <span class="fu">$</span> p <span class="fu">!</span> Person.name'
orderBy personCount <span class="dt">Desc</span>
2016-09-17 10:01:05 +03:00
return <span class="fu">$</span> gbd <span class="fu">&gt;&lt;</span> personCount</code></pre></div>
2014-12-24 13:45:21 +03:00
<p>orders by the number of people born on the same Heisei period dates:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> <span class="kw">ALL</span> T1.day <span class="kw">AS</span> f0, <span class="fu">COUNT</span> (T0.name) <span class="kw">AS</span> f1
2014-12-25 04:23:17 +03:00
<span class="kw">FROM</span> PUBLIC.person T0 <span class="kw">INNER</span> <span class="kw">JOIN</span> PUBLIC.birthday T1
<span class="kw">ON</span> (T0.name = T1.name)
<span class="kw">WHERE</span> (T1.day &gt;= <span class="dt">DATE</span> <span class="st">'1989-01-08'</span>)
2016-09-17 10:01:05 +03:00
<span class="kw">GROUP</span> <span class="kw">BY</span> T1.day <span class="kw">ORDER</span> <span class="kw">BY</span> <span class="fu">COUNT</span> (T0.name) <span class="kw">DESC</span></code></pre></div>
2014-12-25 04:23:17 +03:00
</div><div id="ordering-example-2" class="slide section level2">
<h1>Ordering Example</h1>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> <span class="kw">ALL</span> T1.day <span class="kw">AS</span> f0, <span class="fu">COUNT</span> (T0.name) <span class="kw">AS</span> f1
2014-12-24 11:58:51 +03:00
<span class="kw">FROM</span> PUBLIC.person T0 <span class="kw">INNER</span> <span class="kw">JOIN</span> PUBLIC.birthday T1
<span class="kw">ON</span> (T0.name = T1.name)
<span class="kw">WHERE</span> (T1.day &gt;= <span class="dt">DATE</span> <span class="st">'1989-01-08'</span>)
2016-09-17 10:01:05 +03:00
<span class="kw">GROUP</span> <span class="kw">BY</span> T1.day <span class="kw">ORDER</span> <span class="kw">BY</span> <span class="fu">COUNT</span> (T0.name) <span class="kw">DESC</span></code></pre></div>
2014-12-24 11:58:51 +03:00
</div>
2014-12-24 13:45:21 +03:00
<div id="other-features" class="titleslide slide section level1"><h1>Other Features</h1></div><div id="placeholders" class="slide section level2">
<h1>Placeholders</h1>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">specifyPerson ::</span> <span class="dt">Relation</span> <span class="dt">String</span> (<span class="dt">Person</span>, <span class="dt">Birthday</span>)
2014-12-24 11:58:51 +03:00
specifyPerson <span class="fu">=</span> relation' <span class="fu">$</span> <span class="kw">do</span>
pb <span class="ot">&lt;-</span> query personAndBirthday <span class="co">-- Re-use predefined</span>
2014-12-24 12:14:02 +03:00
(ph, ()) <span class="ot">&lt;-</span> placeholder
(\ph' <span class="ot">-&gt;</span> wheres <span class="fu">$</span> pb <span class="fu">!</span> fst' <span class="fu">!</span> Person.name' <span class="fu">.=.</span> ph')
2016-09-17 10:01:05 +03:00
return (ph, pb)</code></pre></div>
2014-12-24 13:45:21 +03:00
<p>specifies a person name using a placeholder:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> <span class="kw">ALL</span> T2.f0 <span class="kw">AS</span> f0, T2.f1 <span class="kw">AS</span> f1, T2.f2 <span class="kw">AS</span> f2,
2014-12-24 11:58:51 +03:00
T2.f3 <span class="kw">AS</span> f3, T2.f4 <span class="kw">AS</span> f4
2014-12-24 12:14:02 +03:00
<span class="kw">FROM</span> (<span class="kw">SELECT</span> <span class="kw">ALL</span>
T0.name <span class="kw">AS</span> f0, T0.age <span class="kw">AS</span> f1, T0.address <span class="kw">AS</span> f2,
T1.name <span class="kw">AS</span> f3, T1.day <span class="kw">AS</span> f4
2014-12-24 11:58:51 +03:00
<span class="kw">FROM</span> PUBLIC.person T0 <span class="kw">INNER</span> <span class="kw">JOIN</span>
PUBLIC.birthday T1
<span class="kw">ON</span> (T0.name = T1.name)) T2
2016-09-17 10:01:05 +03:00
<span class="kw">WHERE</span> (T2.f0 = ?)</code></pre></div>
2014-12-24 13:45:21 +03:00
</div><div id="map-sql-values-to-a-haskell-record" class="slide section level2">
<h1>Map SQL Values to a Haskell Record</h1>
<p>Mapping to records using Applicative style:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">(|$|) ::</span> (<span class="dt">ProjectableFunctor</span> p, <span class="dt">ProductConstructor</span> (a <span class="ot">-&gt;</span> b))
2014-12-24 11:58:51 +03:00
<span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> b)
<span class="ot">-&gt;</span> p a
<span class="ot">-&gt;</span> p b
<span class="ot">(|*|) ::</span> <span class="dt">ProjectableApplicative</span> p
<span class="ot">=&gt;</span> p (a <span class="ot">-&gt;</span> b)
<span class="ot">-&gt;</span> p a
2016-09-17 10:01:05 +03:00
<span class="ot">-&gt;</span> p b</code></pre></div>
2014-12-24 13:45:21 +03:00
</div><div id="record-mapping---projections" class="slide section level2">
<h1>Record Mapping - Projections</h1>
<p>Assign record types to an SQL projection:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">personAndBirthdayT ::</span> <span class="dt">Relation</span> () <span class="dt">PersonAndBirthday</span>
2014-12-24 11:58:51 +03:00
personAndBirthdayT <span class="fu">=</span> relation <span class="fu">$</span> <span class="kw">do</span>
p <span class="ot">&lt;-</span> query person
b <span class="ot">&lt;-</span> query birthday
wheres <span class="fu">$</span> p <span class="fu">!</span> Person.name' <span class="fu">.=.</span> b <span class="fu">!</span> Birthday.name'
2014-12-24 12:14:02 +03:00
<span class="co">-- Build record phantom type</span>
return <span class="fu">$</span> <span class="dt">PersonAndBirthday</span> <span class="fu">|$|</span> p <span class="fu">|*|</span> b
2014-12-24 11:58:51 +03:00
<span class="ot">(|$|) ::</span> <span class="dt">ProductConstructor</span> (a <span class="ot">-&gt;</span> b)
<span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Projection</span> c a <span class="ot">-&gt;</span> <span class="dt">Projection</span> c b
2016-09-17 10:01:05 +03:00
<span class="ot">(|*|) ::</span> <span class="dt">Projection</span> c (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Projection</span> c a <span class="ot">-&gt;</span> <span class="dt">Projection</span> c b</code></pre></div>
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> <span class="kw">ALL</span> T0.name <span class="kw">AS</span> f0, T0.age <span class="kw">AS</span> f1, T0.address <span class="kw">AS</span> f2,
2014-12-25 04:18:33 +03:00
T1.name <span class="kw">AS</span> f3, T1.day <span class="kw">AS</span> f4
<span class="kw">FROM</span> PUBLIC.person T0 <span class="kw">INNER</span> <span class="kw">JOIN</span> PUBLIC.birthday T1
2016-09-17 10:01:05 +03:00
<span class="kw">ON</span> (T0.name = T1.name)</code></pre></div>
2014-12-24 13:45:21 +03:00
</div><div id="record-mapping---column-selectors" class="slide section level2">
<h1>Record Mapping - Column Selectors</h1>
<p>Column selectors can be mapped to a record:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell">Birthday.day'<span class="ot"> ::</span> <span class="dt">Pi</span> <span class="dt">Birthday</span> <span class="dt">Day</span>
2014-12-24 11:58:51 +03:00
<span class="ot">uncurryPB ::</span> <span class="dt">Pi</span> (<span class="dt">Person</span>, <span class="dt">Birthday</span>) <span class="dt">PersonAndBirthday</span>
uncurryPB <span class="fu">=</span> <span class="dt">PersonAndBirthday</span> <span class="fu">|$|</span> fst' <span class="fu">|*|</span> snd'
<span class="ot">(|$|) ::</span> <span class="dt">ProductConstructor</span> (a <span class="ot">-&gt;</span> b)
<span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Pi</span> r a <span class="ot">-&gt;</span> <span class="dt">Pi</span> r b
2016-09-17 10:01:05 +03:00
<span class="ot">(|*|) ::</span> <span class="dt">Pi</span> r (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Pi</span> r a <span class="ot">-&gt;</span> <span class="dt">Pi</span> r b</code></pre></div>
2014-12-24 13:45:21 +03:00
</div><div id="record-mapping---placeholders" class="slide section level2">
<h1>Record Mapping - Placeholders</h1>
<p>Placeholders can be mapped to a record:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">personAndBirthdayP2 ::</span> <span class="dt">Relation</span> <span class="dt">Person</span> <span class="dt">PersonAndBirthday</span>
2014-12-24 11:58:51 +03:00
personAndBirthdayP2 <span class="fu">=</span> relation' <span class="fu">$</span> <span class="kw">do</span>
p <span class="ot">&lt;-</span> query person
b <span class="ot">&lt;-</span> query birthday
2014-12-25 03:42:21 +03:00
(ph0, ()) <span class="ot">&lt;-</span> placeholder (\ph0' <span class="ot">-&gt;</span> on <span class="fu">$</span> p <span class="fu">!</span> Person.name' <span class="fu">.=.</span> ph0')
(ph1, ()) <span class="ot">&lt;-</span> placeholder (\ph1' <span class="ot">-&gt;</span> on <span class="fu">$</span> p <span class="fu">!</span> Person.age' <span class="fu">.=.</span> ph1')
(ph2, ()) <span class="ot">&lt;-</span> placeholder (\ph2' <span class="ot">-&gt;</span> on <span class="fu">$</span> p <span class="fu">!</span> Person.address' <span class="fu">.=.</span> ph2')
return (<span class="dt">Person</span> <span class="fu">|$|</span> ph0 <span class="fu">|*|</span> ph1 <span class="fu">|*|</span> ph2,
<span class="dt">PersonAndBirthday</span> <span class="fu">|$|</span> p <span class="fu">|*|</span> b)
<span class="ot">(|$|) ::</span> <span class="dt">ProductConstructor</span> (a <span class="ot">-&gt;</span> b)
<span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Placeholders</span> a <span class="ot">-&gt;</span> <span class="dt">Placeholders</span> b
2016-09-17 10:01:05 +03:00
<span class="ot">(|*|) ::</span> <span class="dt">Placeholders</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Placeholders</span> a <span class="ot">-&gt;</span> <span class="dt">Placeholders</span> b</code></pre></div>
2014-12-25 04:18:33 +03:00
<p>Generated SQL:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> <span class="kw">ALL</span> T0.name <span class="kw">AS</span> f0, T0.age <span class="kw">AS</span> f1, T0.address <span class="kw">AS</span> f2,
2014-12-25 04:23:17 +03:00
T1.name <span class="kw">AS</span> f3, T1.day <span class="kw">AS</span> f4
<span class="kw">FROM</span> PUBLIC.person T0 <span class="kw">INNER</span> <span class="kw">JOIN</span> PUBLIC.birthday T1
2016-09-17 10:01:05 +03:00
<span class="kw">ON</span> (((T0.name = ?) <span class="kw">AND</span> (T0.age = ?)) <span class="kw">AND</span> (T0.address = ?))</code></pre></div>
2014-12-25 04:23:17 +03:00
</div><div id="record-mapping---placeholders-1" class="slide section level2">
<h1>Record Mapping - Placeholders</h1>
<p>Generated SQL:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> <span class="kw">ALL</span> T0.name <span class="kw">AS</span> f0, T0.age <span class="kw">AS</span> f1, T0.address <span class="kw">AS</span> f2,
2014-12-25 03:42:21 +03:00
T1.name <span class="kw">AS</span> f3, T1.day <span class="kw">AS</span> f4
<span class="kw">FROM</span> PUBLIC.person T0 <span class="kw">INNER</span> <span class="kw">JOIN</span> PUBLIC.birthday T1
2016-09-17 10:01:05 +03:00
<span class="kw">ON</span> (((T0.name = ?) <span class="kw">AND</span> (T0.age = ?)) <span class="kw">AND</span> (T0.address = ?))</code></pre></div>
2014-12-24 13:45:21 +03:00
</div><div id="record-mapping---record-placeholders" class="slide section level2">
<h1>Record Mapping - Record Placeholders</h1>
<p>Record-typed placeholder:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">placeholder ::</span> (<span class="dt">PersistableWidth</span> t, <span class="dt">Monad</span> m)
2014-12-25 03:42:21 +03:00
<span class="ot">=&gt;</span> (<span class="dt">Projection</span> c t <span class="ot">-&gt;</span> m a) <span class="ot">-&gt;</span> m (<span class="dt">PlaceHolders</span> t, a)
<span class="ot">personAndBirthdayP ::</span> <span class="dt">Relation</span> <span class="dt">Person</span> <span class="dt">PersonAndBirthday</span>
2014-12-24 11:58:51 +03:00
personAndBirthdayP <span class="fu">=</span> relation' <span class="fu">$</span> <span class="kw">do</span>
p <span class="ot">&lt;-</span> query person
b <span class="ot">&lt;-</span> query birthday
(ph, ()) <span class="ot">&lt;-</span> placeholder (\ph' <span class="ot">-&gt;</span> wheres <span class="fu">$</span> p <span class="fu">.=.</span> ph')
2016-09-17 10:01:05 +03:00
return <span class="fu">$</span> (ph, <span class="dt">PersonAndBirthday</span> <span class="fu">|$|</span> p <span class="fu">|*|</span> b)</code></pre></div>
2014-12-25 04:18:33 +03:00
<p>row value of Placeholders:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> <span class="kw">ALL</span> T0.name <span class="kw">AS</span> f0, T0.age <span class="kw">AS</span> f1, T0.address <span class="kw">AS</span> f2,
2014-12-25 03:12:12 +03:00
T1.name <span class="kw">AS</span> f3, T1.day <span class="kw">AS</span> f4
<span class="kw">FROM</span> PUBLIC.person T0 <span class="kw">INNER</span> <span class="kw">JOIN</span> PUBLIC.birthday T1
2016-09-17 10:01:05 +03:00
<span class="kw">ON</span> ((T0.name, T0.age, T0.address) = (?, ?, ?))</code></pre></div>
2014-12-24 13:45:21 +03:00
</div><div id="questions" class="slide section level2">
<h1>Questions?</h1>
2014-12-24 11:58:51 +03:00
</div><div id="window-function" class="slide section level2">
<h1>Window Function</h1>
2014-12-24 13:45:21 +03:00
<p>Monadic-style window building:</p>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">ageRankOfFamilies ::</span> <span class="dt">Relation</span> () ((<span class="dt">Int64</span>, <span class="dt">String</span>), <span class="dt">Int32</span>)
2014-12-24 11:58:51 +03:00
ageRankOfFamilies <span class="fu">=</span> relation <span class="fu">$</span> <span class="kw">do</span>
my <span class="ot">&lt;-</span> query myTable
return <span class="fu">$</span>
rank <span class="ot">`over`</span> <span class="kw">do</span>
partitionBy <span class="fu">$</span> my <span class="fu">!</span> family' <span class="co">-- Monad to build window</span>
orderBy (my <span class="fu">!</span> age') <span class="dt">Desc</span>
<span class="fu">&gt;&lt;</span>
2016-09-17 10:01:05 +03:00
my <span class="fu">!</span> family' <span class="fu">&gt;&lt;</span> my <span class="fu">!</span> age'</code></pre></div>
<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> <span class="kw">ALL</span>
2014-12-29 06:27:17 +03:00
<span class="fu">RANK</span>() <span class="kw">OVER</span> (<span class="kw">PARTITION</span> <span class="kw">BY</span> T0.family
<span class="kw">ORDER</span> <span class="kw">BY</span> T0.age <span class="kw">DESC</span>) <span class="kw">AS</span> f0,
2014-12-25 03:12:12 +03:00
T0.family <span class="kw">AS</span> f1, T0.age <span class="kw">AS</span> f2
2016-09-17 10:01:05 +03:00
<span class="kw">FROM</span> PUBLIC.my_table T0</code></pre></div>
2014-12-24 11:58:51 +03:00
</div><div id="discussion" class="slide section level2">
<h1>Discussion</h1>
2014-12-24 12:14:02 +03:00
</div>
<div id="others" class="titleslide slide section level1"><h1>Others</h1></div><div id="exists-operator" class="slide section level2">
2014-12-24 13:45:21 +03:00
<h1>exists Operator</h1>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">exists ::</span> (<span class="dt">SqlProjectable</span> p, <span class="dt">ProjectableShowSql</span> p)
2014-12-24 12:14:02 +03:00
<span class="ot">=&gt;</span> <span class="dt">ListProjection</span> (<span class="dt">Projection</span> <span class="dt">Exists</span>) r <span class="ot">-&gt;</span> p (<span class="dt">Maybe</span> <span class="dt">Bool</span>)
<span class="ot">queryList ::</span> <span class="dt">MonadQualify</span> <span class="dt">ConfigureQuery</span> m
<span class="ot">=&gt;</span> <span class="dt">Relation</span> () r
2016-09-17 10:01:05 +03:00
<span class="ot">-&gt;</span> m (<span class="dt">ListProjection</span> (<span class="dt">Projection</span> c) r)</code></pre></div>
2014-12-24 11:58:51 +03:00
</div><div id="in-operator" class="slide section level2">
2014-12-24 13:45:21 +03:00
<h1>in' Operator</h1>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">in' ::</span> (<span class="dt">SqlProjectable</span> p, <span class="dt">ProjectableShowSql</span> p)
2014-12-29 06:27:17 +03:00
<span class="ot">=&gt;</span> p t <span class="ot">-&gt;</span> <span class="dt">ListProjection</span> p t <span class="ot">-&gt;</span> p (<span class="dt">Maybe</span> <span class="dt">Bool</span>)
<span class="ot">queryList ::</span> <span class="dt">MonadQualify</span> <span class="dt">ConfigureQuery</span> m
<span class="ot">=&gt;</span> <span class="dt">Relation</span> () r
<span class="ot">-&gt;</span> m (<span class="dt">ListProjection</span> (<span class="dt">Projection</span> c) r)
<span class="ot">values ::</span> (<span class="dt">ShowConstantTermsSQL</span> t, <span class="dt">SqlProjectable</span> p)
2016-09-17 10:01:05 +03:00
<span class="ot">=&gt;</span> [t] <span class="ot">-&gt;</span> <span class="dt">ListProjection</span> p t</code></pre></div>
2014-12-24 13:45:21 +03:00
</div><div id="scalar-queries" class="slide section level2">
<h1>Scalar Queries</h1>
2016-09-17 10:01:05 +03:00
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">queryScalar ::</span> (<span class="dt">MonadQualify</span> <span class="dt">ConfigureQuery</span> m, <span class="dt">ScalarDegree</span> r)
2014-12-24 12:14:02 +03:00
<span class="ot">=&gt;</span> <span class="dt">UniqueRelation</span> () c r
2016-09-17 10:01:05 +03:00
<span class="ot">-&gt;</span> m (<span class="dt">Projection</span> c (<span class="dt">Maybe</span> r))</code></pre></div>
2014-12-24 11:58:51 +03:00
</div>
</div>
</body>
</html>