开发者

Variable as table name using Lisp/Postmodern/PostgreSQL

开发者 https://www.devze.com 2023-03-11 08:29 出处:网络
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?

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
0

精彩评论

暂无评论...
验证码 换一张
取 消