Variable as table name using Lisp/Postmodern/PostgreSQL
Can someone please give an example of how to write a row to a table using a variable as the table name in Lisp/Postmodern/S-SQL/PostgreSQL?
I am currently able to write to a table in PostgreSQL with :insert-into
using the following function:
(defun save-event (table-name cost event-id)
(defprepared insert-event
(sql-compile `(:insert-into ,table-name :set 'cost ,cost
'event-id ,event-id)))
(insert-event))
Using the input syntax:
(save-event 'table-name 33 1)
However, if I try and pass a string containing the desired table name to the function as follows:
(defparameter x "table-name")
(apply #'funcall `(save-event ',x 44 2))
I get the following error message:
开发者_JAVA百科Database error 42601: syntax error at or near "E'table-name'"
Query: INSERT INTO E'table-name' (cost, event_id) VALUES (44, 2)
[Condition of type CL-POSTGRES-ERROR:SYNTAX-ERROR-OR-ACCESS-VIOLATION]
I have been stuck on this for quite a while, tried almost everything. Got me stumped.
If the code expects a symbol as table name you cannot pass a string, you must intern
it.
Something like the following should work...
(defparameter x "table-name")
(save-event (intern x) 44 2)
In common lisp a symbol is a symbol and a string is a string. To get a string from a symbol you need to call (symbol-name x)
to get a symbol from a string you need to call (intern x)
.
Quasiquoting (back quoting) is not going to do this transformation. In other words:
(let ((test "foo"))
`(this is a ,test))
--> (THIS IS A "foo")`
Depending on how the symbol is going to be used by that library may be even an "uninterned" symbol can be used instead of a regular interned symbol.
Those symbols can be created with (make-symbol x)
but if this is acceptable or not depends on how the symbol is being used in the code; note also that while (intern x)
will always return the same symbol if you call it multiple times with the same string this is not true for (make-symbol x)
that instead will return a different fresh uninterned symbol each time is called.
(make-symbol "X")
--> #:X
(symbol-name (make-symbol "X"))
--> "X"
(eq (make-symbol "X") (make-symbol "X"))
--> NIL
(eq (intern "X") (intern "X"))
--> T
精彩评论