Queries in general purpose languages

22
Queries in general- purpose programming languages

Transcript of Queries in general purpose languages

Page 1: Queries in general purpose languages

Queries in general-purpose programming languages

Page 2: Queries in general purpose languages

Languages

Theory Relational algebra Monads and comprehensions

Haskell and Links Monad comprehensions Comprehensions with group and order

C# and F# Language integrated query (LINQ) Extensible query syntax in F# 3.0

Page 3: Queries in general purpose languages

Problems

Expressing queries What operations can we use? What is the right syntax for queries? Should the syntax be extensible?

Compiling queries How to turn normal code to SQL? How to turn normal code to efficient SQL? Dealing with functions in SQL code

Page 4: Queries in general purpose languages

Theory

Relational algebra Selection () and projection () Cartesian product () Set union () and difference ()

Monad comprehensions Monadic bind [ … | x <- <e> ] Monadic return [ <e> | … ] Conditional [ … | …, <e> ]

Page 5: Queries in general purpose languages

Monads and monad comprehensions in Haskell

Page 6: Queries in general purpose languages

Monad comprehensions

Query example

Translation using monads bind return zero

[ p.Name | p <- db.Products, p.Price > 10 ]

db.Products `bind` (\p -> if (p.Price > 10) then return p.Name else zero)

Page 7: Queries in general purpose languages

Monadic bind and joins

Join using comprehensions

Translation using monads

Multiple uses of bind are nested Second data source may depend on values from first!

[ (p.Name, c.CategoryName) | p <- db.Products, c <- db.Categories , p.CategoryID = c.ID ]

db.Products `bind` (\p -> db.Categories `bind` (\c -> if (p.CategoryID = c.ID) then return (p.Name, c.CategoryName) else zero))

Page 8: Queries in general purpose languages

Comparing bind and join

Standard join Two independent data sources Equality condition on some projected values

But bind allows more Second data source may depend on first Can use arbitrary conditions

[ (p, c) | p <- db.Products, c <- db.Categories , p.CategoryID = c.ID ]

[ (p1.Name, p2.Name) | p1 <- Products , p2 <- [ p | p <- Products, p.Price > p1.Price ] ]

Page 9: Queries in general purpose languages

Adding ordering and grouping

“Ordering” signature Functions of type like:

reverse, orderBy (also needs a key selector)take, takeWhile, skip, … (also needs count or predicate)

“Grouping” signature Functions of type like:

groupBy, groupAdjacent (also needs a key selector)

Are we missing anything else?

Page 10: Queries in general purpose languages

Adding ordering and groupingOrdering syntax

The function to use follows then keyword by clause is optional argument (of type

Grouping syntax

Grouping function implicit, but can be set with using The by clause is optional

[ p | p <- db.Products, then reverse ][ p | p <- db.Products, then order by p.Price ]

[ p | …, then group by p.CategoryID ][ p | …, then group by p.CategoryID using groupAdj ]

Page 11: Queries in general purpose languages

SQL-style relationalqueries in LINQ using C#

Page 12: Queries in general purpose languages

LINQ Overview

Query example

Translating to SQL All operations have a corresponding method

Lambda function translated as expression tree Expression trees composed and processed

from p in db.Products join c in db.Categories on p.CategoryID equals c.IDselect new { p.Name, c.CategoryName }

db.Products.Where(p => p.Price > 10)db.Products.Select(p => p.Name)

Page 13: Queries in general purpose languages

Expressing queriesSelection and projection

Ordering

Grouping

Joins (products with selection)

from p in db.Products where p.Price > 10 select pfrom p in db.Products select p.Name

from p in db.Products orderby p.Price select p

from p in db.Products group p by p.CategoryID

from p in db.Products join c in db.Categories on p.CategoryID equals c.IDselect new { ... }

Page 14: Queries in general purpose languages

Customizing LINQ operators

Operations depend on the data source Syntax is translated to method calls

Wrap collection and then use different operator

Various applications LINQ over events, Parallel implementation

from p in db.Products group p by p.CategoryIDdb.Products.GroupBy(p => p.CategoryID)

from p in db.Products.WithAdjacentGrouping() group p by p.CategoryIDWithAdjacentGrouping : IE<T> -> IEWithGroup<T>GroupBy : IEWithGroup<T> -> IEWithGroup<IEWithGroup<T>>

Page 15: Queries in general purpose languages

Writing joins in LINQ

Syntax for joins Independent sources; equality condition only

Using multiple from clauses Later from can depend on previous variables We can write arbitrary conditions

from p in db.Products join c in db.Categories on p.CategoryID equals c.IDselect …

from p in db.Products from c in db.Categories.Where(c => p.CategoryID == c.ID)where c.Name != "Stuff"

Page 16: Queries in general purpose languages

Joins and theoryMultiple from clauses Uses an operation similar to Bind

Can be implemented using Bind

Syntax for joins Can be defined using SelectMany, but not vice versa

Resembles operation of “applicative functors”

SelectMany : M<S> -> (S -> M<C>) -> (S * C -> R) -> M<R>

Bind : M<S> -> (S -> M<R>) -> M<R>StrengthL : V * M<S> -> M<V * S>

Join : M<A> -> M<B> -> (A -> K) -> (B -> K) -> (A * B -> R) -> M<R>

Page 17: Queries in general purpose languages

More flexible queries in F# 3.0

Page 18: Queries in general purpose languages

Queries in F# 3.0

Design between Haskell and C# Can define custom operations

Here orderBy and takeWhile are not built-in

Two kinds of custom operations Preserve variable scope (orderBy, where, …) Require re-binding (groupBy)

query { for p in db.Products do orderBy p.Price takeWhile (p.Price > 100) }

Page 19: Queries in general purpose languages

What can be done in F# 3.0?Better queries for OData Open standard for REST based queries Supports only subset of query operations

Expanding dependent tables explicitly

Wrong! We did not say we will use Awards

Other interesting areas: NoSQL, etc.

query { for title in db.Movies do select title.Awards }

query { for title in db.Movies do expand title.Awards select title.Awards }

Page 20: Queries in general purpose languages

Some questions about queries that I’m interested in…

Page 21: Queries in general purpose languages

Possible questionsAdvanced type checking Translating custom functions to SQL Limiting operations and allowed patterns (OData)

Expressivity What are other join-like operations? Aren’t monads and bind too powerful? Are we missing other important operations? What else is there than just lists…

Classical problems Optimizing queries, efficient compilation

Page 22: Queries in general purpose languages

References

Haskell and comprehensions Comprehensive Comprehensions:

comprehensions with "Order by" and "Group by" Bringing Back Monad Comprehensions Monad Comprehensions:

A Versatile Representation for Queries

LINQ, C# and F# C# Language Specification msdn.microsoft.com/en-us/library/bb397676.aspx tomasp.net/blog/idioms-in-linq.aspx