#lang scheme/base
(require srfi/19
srfi/26
(planet untyped/unlib:3/time)
(planet untyped/unlib:3/symbol)
"../base.ss"
"../era/era.ss")
(define-struct source () #:transparent)
(define-struct (source-alias source) (name value) #:transparent)
(define-struct (table-alias source-alias) () #:transparent)
(define-struct (select-alias source-alias) () #:transparent)
(define (source-alias-columns alias)
(if (table-alias? alias)
(map (cut create-attribute-alias alias <>)
(table-attributes (source-alias-value alias)))
(select-what (source-alias-value alias))))
(define-struct (join source) (op left right on) #:transparent)
(define-struct expression (type) #:transparent)
(define-struct (column expression) (name allow-null? default) #:transparent)
(define-struct (attribute-alias column) (table attribute) #:transparent)
(define (create-attribute-alias table attr)
(make-attribute-alias (attribute-type attr)
(symbol-append (source-alias-name table) '- (attribute-name attr))
table
attr))
(define-struct (expression-alias column) (value) #:transparent)
(define (create-expression-alias name value)
(make-expression-alias (expression-type value) name value))
(define-struct (function expression) (op args) #:transparent)
(define-struct (aggregate function) () #:transparent)
(define-struct (literal expression) (value) #:transparent)
(define (create-literal val)
(cond [(boolean? val) (make-literal type:boolean val)]
[(integer? val) (make-literal type:integer val)]
[(real? val) (make-literal type:real val)]
[(string? val) (make-literal type:string val)]
[(symbol? val) (make-literal type:symbol val)]
[(time-utc? val) (make-literal type:time-utc val)]
[(time-tai? val) (make-literal type:time-tai val)]
[else (raise-exn exn:fail:contract
(format "Expected (U boolean integer real string symbol time-tai time-utc), received ~s" val))]))
(define (create-null type)
(make-literal type (type-null type)))
(define-struct order (expression direction) #:transparent)
(define-struct select
(what distinct from where group order having limit offset local-columns imported-columns)
#:transparent)
(define (source+select? item)
(or (source? item)
(select? item)))
(define (literal-value? item)
(or (boolean? item)
(integer? item)
(real? item)
(string? item)
(symbol? item)
(time-tai? item)
(time-utc? item)))
(define (quotable? item)
(or (expression? item)
(literal-value? item)
(select? item)
(select-alias? item)))
(define (quote-argument arg)
(cond [(expression? arg) arg]
[(source? arg) arg]
[(literal-value? arg) (create-literal arg)]
[(select? arg) (make-select-alias (string->symbol (symbol->string (gensym 'subq))) arg)]
[else (raise-exn exn:fail:contract
(format "Expected (opt-listof (U expression select boolean integer real string symbol time-tai time-utc)), received ~s" arg))]))
(define function-arg/c
(or/c expression? select-alias? table-alias? select? (listof expression?)))
(define aggregate-arg/c
(or/c function-arg/c table-alias? select-alias?))
(define source/c
(or/c table-alias? select-alias?))
(provide (except-out (struct-out attribute-alias) make-attribute-alias)
(except-out (struct-out expression-alias) make-expression-alias)
(except-out (struct-out literal) make-literal)
(rename-out (create-attribute-alias make-attribute-alias))
(rename-out (create-expression-alias make-expression-alias))
(rename-out (create-literal make-literal))
(rename-out (create-null make-null))
quotable?
quote-argument
source+select?
source/c)
(provide/contract
[struct source ()]
[struct (source-alias source) ([name symbol?] [value (or/c table? select?)])]
[struct (table-alias source-alias) ([name symbol?] [value table?])]
[struct (select-alias source-alias) ([name symbol?] [value select?])]
[struct (join source) ([op symbol?] [left source?] [right source?] [on (or/c expression? false/c)])]
[struct expression ([type type?])]
[struct (column expression) ([type type?] [name symbol?])]
[struct (function expression) ([type type?] [op symbol?] [args (listof function-arg/c)])]
[struct (aggregate function) ([type type?] [op symbol?] [args (listof function-arg/c)])]
[struct order ([expression expression?] [direction (symbols 'asc 'desc)])]
[struct select ([what (listof column?)]
[distinct (or/c (listof expression?) false/c)]
[from source?]
[where (or/c expression? false/c)]
[group (listof expression?)]
[order (listof order?)]
[having (or/c expression? false/c)]
[limit (or/c integer? false/c)]
[offset (or/c integer? false/c)]
[local-columns (listof column?)]
[imported-columns (listof column?)]
[extract-info (or/c table? type? (listof (or/c table? type?)))])]
[source-alias-columns (-> source-alias? (listof column?))])