rmculpepper / sql

Embedding of some of SQL into Racket
33 stars 5 forks source link

Parameterizing #:order-by #1

Open greghendershott opened 7 years ago

greghendershott commented 7 years ago

First, this is a fantastic library -- thanks! I only discovered it yesterday so I'm still wrapping my head around it, but the documentation is really good.

The only wall I've hit so far:

I'd like to use placeholders for #:order-by. (Motivation: Imagine a query that wants to reflect a user clicking column headers.)

But trying to use

#:order-by ,order-by-column

gives an error because the SelectOrderItem syntax pattern uses ScalarExpr:

(define-splicing-syntax-class SelectOrderItem
  #:attributes (ast)
  (pattern (~seq e:ScalarExpr o:SelectOrderDirection)
           #:attr ast (select:order ($ e.ast) ($ o.dir))))

whereas later emit-select-order uses emit-name:

    (define/public (emit-select-order so)
      (match so
        [(select:order column asc/desc)
         (J (emit-name column) ;; <--- should be (emit-scalar-expr column) ???
            (case asc/desc
              [(asc) " ASC"]
              [(desc) " DESC"]
              [(#f) ""]))]))

In addition, I'm not sure how to specify #:asc or #:desc keywords for the direction, using placeholders?


I tried hacking the latter instead to use emit-scalar-expression. This way, I can at least do something like

#:order-by (ScalarExpr:INJECT ,(format "~a ~a" order-by-column order-by-direction))

and "it works". Albeit using INJECT isn't ideal.


Is this pilot error? Or if there's a bug/omission, is my change a reasonable fix I should PR, or a bad hack?

Thanks!

rmculpepper commented 7 years ago

You're right, that code should use emit-scalar-expr instead of emit-name. I'll push the change.

Placeholders can only stand for SQL scalar constants, not expressions or things like order directions. Abusing ScalarExpr:INJECT is probably the best solution for now.

Longer-term, I could imagine adding more dynamic AST manipulation support and more nonterminal escapes, so you could write something like

#:order-by (SelectOrderItem:AST
            ,(make-SelectOrderItem (make-Ident column-name)
                                   (if asc? 'asc 'desc)))