macroscommon-lispclsql

CL Macro does not resolve properly


In Common Lisp I have defind this macro:

(defmacro gen-update-func (func-name table id keyparam)
  `(defun ,func-name (db ,id)
     (let ((data))
       (keyparams ,keyparam)

       (clsql:update-records ',table
                 :database db
                 :where [= ',id id]
                 :av-pairs data))))

I call it with:

(gen-update-func add-sp spender spenderid (vorname name))

macroexpand-1 returns this:

(defun add-sp (db spenderid)
  (let ((data))
    ;(keyparams (vorname name))
    (clsql-sys:update-records 'spender :database db :where [= 'spenderid id]
                              :av-pairs data)))

This is expected.

When I call it, it resolves the line ":where [= ',id id]" to:

:WHERE SPENDENDB::[= 'SPENDENDB::SPENDERID SPENDENDB::ID]

This is wrong. I want to insert [= literally without leading SPENDENDB::. This is intended:

:WHERE [= 'SPENDENDB::SPENDERID SPENDENDB::ID]

How can I achieve that?

The syntax [= ... ] is a special SQL syntax from clsql.


Solution

  • In the file where you define your macro, you are using the [= ...] syntax but you are probably not in the appropriate readtable to do so. This is why [= is parsed as a symbol, which is why it is printed with the package prefix later.

    According to the CLSQL documentation - locally enable sql reader syntax, you should be able to enable the syntax when defining the macro:

    #.(locally-enable-sql-reader-syntax)
        
    (defmacro ...)
        
    #.(restore-sql-reader-syntax-state)
      
    

    Alternatively, you enable it inside a file:

    (in-package :my-package)
    (clsql:file-enable-sql-reader-syntax)
    

    When trying to use this syntax, I wrote:

    * '[= 'a b]
    (CLSQL-SYS:SQL-= 'A B)
    

    As a consequence, you could directly use the equality operator (clsql-sys:sql-= ...) without relying on the helper syntax. Looking at the documentation it is a bit more portable apparently to do it as follows:

    `(clsql-sys:sql-operation '= ,a ,b)