- Standard library
- let my_func = param1 param2 … -> body_expr
- ```
- Where:
- * my_func is the name of the function
- * param1 is the first parameter optionally followed by a type in “< … >”
- * param2 etc. follow the same pattern as param1
- * <return_type> is the type of result wrapped in “< … >”
- * body_expr defines the function body that creates the result.
- It can be PRQL code or internal ... to indicate internal compiler code.
- Operators
- Types
- TODO: an array of anything, not just nulls
- Functions
- These return either a scalar when used within aggregate, or a column when used anywhere else.
- Counts number of items in the column.
- Note that the count will include null values.
- Deprecated in favour of filterning input to the [std.count] function (not yet implemented).
- Mathematical functions
- Deprecated, will be removed in 0.12.0
Standard library
The standard library currently contains commonly used functions that are used in SQL. It’s not yet as broad as we’d like, and we’re very open to expanding it.
Currently s-strings are an escape-hatch for any function that isn’t in our standard library. If we find ourselves using them for something frequently, raise an issue and we’ll add it to the stdlib.
Here’s the source of the current PRQL std:
Note
PRQL 0.9.0 has started supporting different DB implementations for standard library functions. The source is the std.sql.
1. # The PRQL standard library defines the following functions and transforms.
2. # The definitions are whitespace insensitive, and have this form:
3. #
4. #
let my_func = param1 param2 … -> body_expr
```
Where:
* my_func is the name of the function
* param1 is the first parameter optionally followed by a type in “< … >”
* param2 etc. follow the same pattern as param1
* <return_type> is the type of result wrapped in “< … >”
* body_expr defines the function body that creates the result.
It can be PRQL code or internal ... to indicate internal compiler code.
Operators
let mul = left right -> internal std.mul let div_i = left right -> internal std.div_i let div_f = left right -> internal std.div_f let mod = left right -> internal std.mod let add = left right -> internal std.add let sub = left right -> internal std.sub let eq = left right -> internal std.eq let ne = left right -> internal std.ne let gt = left right -> internal std.gt let lt = left right -> internal std.lt let gte = left right -> internal std.gte let lte = left right -> internal std.lte let and = left right -> internal std.and let or = left right -> internal std.or let coalesce = left right -> internal std.coalesce let regex_search = text pattern -> internal std.regex_search
let neg = expr -> internal std.neg let not = expr -> internal std.not
Types
Type primitives
type int = int
type float = float
type bool = bool
type text = text
type date = date
type time = time
type timestamp = timestamp
type func = func
type anytype = anytype
Generic array
TODO: an array of anything, not just nulls
type array = [anytype]
Scalar
type scalar = int || float || bool || text || date || time || timestamp || null type tuple = {..anytype}
Range
type range = {start = scalar, end = scalar}
Relation (an array of tuples)
type relation = [tuple]
Transform
type transform = func relation -> relation
Functions
Relational transforms
let from = func
default_db.source
-> source
let select = func columns tbl -> internal select
let filter = func condition tbl -> internal filter
let derive = func columns tbl -> internal derive
let aggregate = func columns tbl -> internal aggregate
let sort = func by tbl -> internal sort
let take = func expr tbl -> internal take
let join = func
default_db.with
condition
noresolve.side:inner
tbl
-> internal join
let group = func by pipeline tbl -> internal group
let window = func rows:0..-1 range:0..-1 expanding :false rolling :0 pipeline tbl -> internal window
let append = default_db.bottom top -> internal append
let intersect = default_db.bottom top -> (
t = top
join (b = bottom) (tuple_every (tuple_map _eq (tuple_zip t. b.)))
select t.)
let remove = default_db.bottom top -> (
t = top
join side:left (b = bottom) (tuple_every (tuple_map _eq (tuple_zip t. b.)))
filter (tuple_every (tuple_map _is_null b.))
select t.*
)
let loop = func
pipeline
top
-> internal loop
Aggregate functions
These return either a scalar when used within aggregate, or a column when used anywhere else.
let min = column -> internal std.min
let max = column -> internal std.max
let sum = column -> internal std.sum
let average = column -> internal std.average
let stddev = column -> internal std.stddev
let all = column -> internal std.all
let any = column -> internal std.any
let concat_array = column -> internal std.concat_array
Counts number of items in the column.
Note that the count will include null values.
let count = column -> internal count
Deprecated in favour of filterning input to the [std.count] function (not yet implemented).
@{deprecated} let count_distinct = column -> internal std.count_distinct
Window functions
let lag = offset column -> internal std.lag let lead = offset column -> internal std.lead let first = column -> internal std.first let last = column -> internal std.last let rank = column -> internal std.rank let rank_dense = column -> internal std.rank_dense let row_number = column -> internal row_number
Mathematical functions
module math { let abs = column -> internal std.math.abs let floor = column -> internal std.math.floor let ceil = column -> internal std.math.ceil let pi = -> internal std.math.pi let exp = column -> internal std.math.exp let ln = column -> internal std.math.ln let log10 = column -> internal std.math.log10 let log = base column -> internal std.math.log let sqrt = column -> internal std.math.sqrt let degrees = column -> internal std.math.degrees let radians = column -> internal std.math.radians let cos = column -> internal std.math.cos let acos = column -> internal std.math.acos let sin = column -> internal std.math.sin let asin = column -> internal std.math.asin let tan = column -> internal std.math.tan let atan = column -> internal std.math.atan let pow = exponent column -> internal std.math.pow let round = n_digits column -> internal std.math.round }
Misc functions
let as = noresolve.type column -> internal std.as
let in = pattern value -> internal in
Tuple functions
let tuple_every = func list -> internal tuple_every let tuple_map = func fn list -> internal tuple_map let tuple_zip = func a b -> internal tuple_zip let _eq = func a -> internal _eq let _is_null = func a -> _param.a == null
Misc
let from_text = input noresolve.format:csv -> internal from_text
Text functions
module text { let lower = column -> internal std.text.lower let upper = column -> internal std.text.upper let ltrim = column -> internal std.text.ltrim let rtrim = column -> internal std.text.rtrim let trim = column -> internal std.text.trim let length = column -> internal std.text.length let extract = offset length column -> internal std.text.extract let replace = pattern replacement column -> internal std.text.replace let starts_with = prefix column -> internal std.text.starts_with let contains = substr column -> internal std.text.contains let ends_with = suffix column -> internal std.text.ends_with }
Date functions
module date { let to_text = format column -> internal std.date.to_text }
File-reading functions, primarily for DuckDB
let read_parquet = source -> internal std.read_parquet let read_csv = source -> internal std.read_csv
PRQL compiler functions
module prql {
let version = -> internal prql_version
}
Deprecated, will be removed in 0.12.0
let prql_version = -> internal prql_version
2. And a couple of examples:
4. #### [PRQL](#prql)
from employees
derive {
gross_salary = (salary + payroll_tax | as int),
gross_salary_rounded = (gross_salary | math.round 0),
time = s”NOW()”, # an s-string, given no now function exists in PRQL
}
2. #### [SQL](#sql)
SELECT *, CAST(salary + payroll_tax AS int) AS gross_salary, ROUND(CAST(salary + payroll_tax AS int), 0) AS gross_salary_rounded, NOW() AS time FROM employees
2. Example of different implementations of division and integer division:
4. #### [PRQL](#prql-1)
prql target:sql.sqlite
from [{x = 13, y = 5}] select { quotient = x / y, int_quotient = x // y, }
2. #### [SQL](#sql-1)
WITH table_0 AS ( SELECT 13 AS x, 5 AS y ) SELECT (x 1.0 / y) AS quotient, ROUND(ABS(x / y) - 0.5) SIGN(x) * SIGN(y) AS int_quotient FROM table_0
2. #### [PRQL](#prql-2)
prql target:sql.mysql
from [{x = 13, y = 5}] select { quotient = x / y, int_quotient = x // y, }
2. #### [SQL](#sql-2)
WITH table_0 AS ( SELECT 13 AS x, 5 AS y ) SELECT (x / y) AS quotient, (x DIV y) AS int_quotient FROM table_0
```
