Переменная в качестве имени таблицы с использованием Lisp / Postmodern / PostgreSQL - PullRequest
2 голосов
/ 09 июня 2011

Может кто-нибудь привести пример того, как записать строку в таблицу, используя переменную в качестве имени таблицы в Lisp / Postmodern / S-SQL / PostgreSQL?

В настоящее время я могу записывать в таблицу в PostgreSQL с :insert-into, используя следующую функцию:

(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))

Использование синтаксиса ввода:

(save-event 'table-name 33 1)

Однако, если я попытаюсь передать строку, содержащую желаемое имя таблицы, функции следующим образом:

(defparameter x "table-name")
(apply #'funcall `(save-event ',x 44 2))

Я получаю следующее сообщение об ошибке:

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]

Я застрял на этом довольно долго, перепробовал почти все. Получил меня в тупик.

1 Ответ

3 голосов
/ 09 июня 2011

Если код ожидает символ в качестве имени таблицы, вы не можете передать строку, вы должны intern ее.Должно работать что-то вроде следующего ...

(defparameter x "table-name")
(save-event (intern x) 44 2)

В общем lisp символ - это символ, а строка - это строка.Чтобы получить строку из символа, вам нужно вызвать (symbol-name x), чтобы получить символ из строки, вам нужно вызвать (intern x).

Квазицитирование (обратное цитирование) не будет выполнять это преобразование.Другими словами:

(let ((test "foo"))
  `(this is a ,test))
--> (THIS IS A "foo")`

В зависимости от того, как символ будет использоваться этой библиотекой, может быть даже «неинтернизированный» символ вместо обычного интернированного символа.

Эти символы могут быть созданы с помощью (make-symbol x), но если это приемлемо или нет, зависит от того, как символ используется в коде;также обратите внимание, что хотя (intern x) всегда будет возвращать один и тот же символ, если вы вызываете его несколько раз с одной и той же строкой, это не соответствует действительности для (make-symbol x), который вместо этого будет возвращать новый свежий непереданный символ каждый раз, когда вызывается.

(make-symbol "X")
--> #:X

(symbol-name (make-symbol "X"))
--> "X"

(eq (make-symbol "X") (make-symbol "X"))
--> NIL

(eq (intern "X") (intern "X"))
--> T
...