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" / >
2014-12-29 06:09:11 +03:00
< 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" > < -< / span > xs, y < span class = "ot" > < -< / 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" > < -< / span > xs; y < span class = "ot" > < -< / 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" > < -< / span > query person < span class = "co" > -- Join product accumulated< / span >
b < span class = "ot" > < -< / 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" > > < < / 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" > => < / span > < span class = "dt" > Relation< / span > () r
< span class = "ot" > -> < / span > m (< span class = "dt" > Projection< / span > < span class = "dt" > Flat< / span > r)
< span class = "co" > -- Used for outer join< / span >
2014-12-29 06:09:11 +03:00
< 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" > => < / span > < span class = "dt" > Relation< / span > () r
< span class = "ot" > -> < / 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" > => < / span > < span class = "dt" > Projection< / span > < span class = "dt" > Flat< / span > (< span class = "dt" > Maybe< / span > < span class = "dt" > Bool< / span > ) < span class = "ot" > -> < / 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" > < -< / span > query person
b < span class = "ot" > < -< / 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" > > < < / 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" > => < / 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" > -> < / 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" > -> < / 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" > => < / span > < span class = "dt" > Projection< / span > < span class = "dt" > Flat< / span > a < span class = "ot" > -> < / span > < span class = "dt" > Projection< / span > < span class = "dt" > Aggregated< / span > (< span class = "dt" > Maybe< / span > a)< / code > < / pre > < / div >
2014-12-29 06:09:11 +03:00
< 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" > < -< / span > query myTable
gFam < span class = "ot" > < -< / 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" > > < < / 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" > => < / span > < span class = "dt" > Projection< / span > c (< span class = "dt" > Maybe< / span > < span class = "dt" > Bool< / span > )
< span class = "ot" > -> < / span > m ()
< span class = "ot" > wheres ::< / span > < span class = "dt" > MonadRestrict< / span > < span class = "dt" > Flat< / span > m
< span class = "ot" > => < / 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" > -> < / 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" > => < / span > < span class = "dt" > Projection< / span > c (< span class = "dt" > Maybe< / span > < span class = "dt" > Bool< / span > )
< span class = "ot" > -> < / span > m ()
< span class = "ot" > having ::< / span > < span class = "dt" > MonadRestrict< / span > < span class = "dt" > Aggregated< / span > m
< span class = "ot" > => < / 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" > -> < / 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" > < -< / span > query person
b < span class = "ot" > < -< / 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" > .> =.< / span > value (fromGregorian < span class = "dv" > 1989< / span > < span class = "dv" > 1< / span > < span class = "dv" > 8< / span > )
gbd < span class = "ot" > < -< / 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" > .> .< / span > value < span class = "dv" > 1< / span >
2016-09-17 10:01:05 +03:00
return < span class = "fu" > $< / span > gbd < span class = "fu" > > < < / 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 > = < 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) > < 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 > = < 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) > < 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" > < -< / span > query person
b < span class = "ot" > < -< / 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" > .> =.< / span > value (fromGregorian < span class = "dv" > 1989< / span > < span class = "dv" > 1< / span > < span class = "dv" > 8< / span > )
gbd < span class = "ot" > < -< / 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" > .> .< / span > value < span class = "dv" > 1< / span >
2016-09-17 10:01:05 +03:00
return < span class = "fu" > $< / span > gbd < span class = "fu" > > < < / 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" > => < / span > < span class = "dt" > Projection< / span > c t
< span class = "co" > -- ^ Ordering terms to add< / span >
< span class = "ot" > -> < / span > < span class = "dt" > Order< / span >
< span class = "co" > -- ^ Order direction -- Asc | Desc< / span >
< span class = "ot" > -> < / 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" > < -< / span > query person
b < span class = "ot" > < -< / 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" > > < < / 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" > < -< / span > query person
b < span class = "ot" > < -< / 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" > .> =.< / span > value (fromGregorian < span class = "dv" > 1989< / span > < span class = "dv" > 1< / span > < span class = "dv" > 8< / span > )
gbd < span class = "ot" > < -< / 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" > > < < / 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 > = < 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 > = < 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" > < -< / span > query personAndBirthday < span class = "co" > -- Re-use predefined< / span >
2014-12-24 12:14:02 +03:00
(ph, ()) < span class = "ot" > < -< / span > placeholder
(\ph' < span class = "ot" > -> < / 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" > -> < / span > b))
2014-12-24 11:58:51 +03:00
< span class = "ot" > => < / span > (a < span class = "ot" > -> < / span > b)
< span class = "ot" > -> < / span > p a
< span class = "ot" > -> < / span > p b
< span class = "ot" > (|*|) ::< / span > < span class = "dt" > ProjectableApplicative< / span > p
< span class = "ot" > => < / span > p (a < span class = "ot" > -> < / span > b)
< span class = "ot" > -> < / span > p a
2016-09-17 10:01:05 +03:00
< span class = "ot" > -> < / 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" > < -< / span > query person
b < span class = "ot" > < -< / 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" > -> < / span > b)
< span class = "ot" > => < / span > (a < span class = "ot" > -> < / span > b) < span class = "ot" > -> < / span > < span class = "dt" > Projection< / span > c a < span class = "ot" > -> < / 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" > -> < / span > b) < span class = "ot" > -> < / span > < span class = "dt" > Projection< / span > c a < span class = "ot" > -> < / 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" > -> < / span > b)
< span class = "ot" > => < / span > (a < span class = "ot" > -> < / span > b) < span class = "ot" > -> < / span > < span class = "dt" > Pi< / span > r a < span class = "ot" > -> < / 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" > -> < / span > b) < span class = "ot" > -> < / span > < span class = "dt" > Pi< / span > r a < span class = "ot" > -> < / 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" > < -< / span > query person
b < span class = "ot" > < -< / span > query birthday
2014-12-25 03:42:21 +03:00
(ph0, ()) < span class = "ot" > < -< / span > placeholder (\ph0' < span class = "ot" > -> < / span > on < span class = "fu" > $< / span > p < span class = "fu" > !< / span > Person.name' < span class = "fu" > .=.< / span > ph0')
(ph1, ()) < span class = "ot" > < -< / span > placeholder (\ph1' < span class = "ot" > -> < / span > on < span class = "fu" > $< / span > p < span class = "fu" > !< / span > Person.age' < span class = "fu" > .=.< / span > ph1')
(ph2, ()) < span class = "ot" > < -< / span > placeholder (\ph2' < span class = "ot" > -> < / 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" > -> < / span > b)
< span class = "ot" > => < / span > (a < span class = "ot" > -> < / span > b) < span class = "ot" > -> < / span > < span class = "dt" > Placeholders< / span > a < span class = "ot" > -> < / 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" > -> < / span > b) < span class = "ot" > -> < / span > < span class = "dt" > Placeholders< / span > a < span class = "ot" > -> < / 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" > => < / span > (< span class = "dt" > Projection< / span > c t < span class = "ot" > -> < / span > m a) < span class = "ot" > -> < / 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" > < -< / span > query person
b < span class = "ot" > < -< / span > query birthday
(ph, ()) < span class = "ot" > < -< / span > placeholder (\ph' < span class = "ot" > -> < / 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" > < -< / 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" > > < < / span >
2016-09-17 10:01:05 +03:00
my < span class = "fu" > !< / span > family' < span class = "fu" > > < < / 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" > => < / span > < span class = "dt" > ListProjection< / span > (< span class = "dt" > Projection< / span > < span class = "dt" > Exists< / span > ) r < span class = "ot" > -> < / 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" > => < / span > < span class = "dt" > Relation< / span > () r
2016-09-17 10:01:05 +03:00
< span class = "ot" > -> < / 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" > => < / span > p t < span class = "ot" > -> < / span > < span class = "dt" > ListProjection< / span > p t < span class = "ot" > -> < / 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" > => < / span > < span class = "dt" > Relation< / span > () r
< span class = "ot" > -> < / 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" > => < / span > [t] < span class = "ot" > -> < / 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" > => < / span > < span class = "dt" > UniqueRelation< / span > () c r
2016-09-17 10:01:05 +03:00
< span class = "ot" > -> < / 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 >