klimenko-serj / cl-fbclient

Common Lisp library for working with firebird databases
6 stars 0 forks source link

Не поддерживается sql-тип с номером 520 (видимо BLOB) #8

Open LinkFly opened 10 years ago

LinkFly commented 10 years ago

Не получается выполнить следующий запрос к системной таблице rdb$generators :

"select rdb$generator_name,rdb$generator_id,rdb$description from rdb$generators where rdb$system_flag=0"

Вероятная причина: отсутствие поддержки sql-типа с номером 520, судя по биндингу для LUA (http://code.google.com/p/fbclient/source/browse/lua/fbclient/xsqlda.lua?r=a257d7ec89a8a185e035eb8baaa5c490a3c9bd0d) - этим типом является SQL_Blob.

CL-USER 4 > (cl-fbclient:fb-query-fetch-all sql-db::default-database "select rdb$generator_name,rdb$generator_id,rdb$description from rdb$generators where rdb$system_flag=0") Uncknown type #520! Uncknown type #520! Uncknown type #520! Uncknown type #520! Uncknown type #520! Uncknown type #520! Uncknown type #520!

Error: unknown CFFI type: nil. 1 (abort) Return to level 0. 2 Return to top loop level 0.

Type :b for backtrace or :c

CL-USER 5 : 1 >

klimenko-serj commented 10 years ago

да. BLOB и Array пока не поддерживаются. В воскресенье займусь.

LinkFly commented 10 years ago

Ок. Предлагаю, для определённости - пораньше сигнализировать об ошибке о не поддерживаемом типе. Сейчас выявлено что если поле DESCRIPTION генератора не содержит значения, то ошибки не происходит (только выводится Uncknown type #520!). Я так понял, это чтобы можно было продолжать выполнение если в полях с неподдерживаемым типом нет значения, т.е. NULL. Сейчас попробую, сделать временный патч, чтобы возвращалось NIL вместо ошибки (как будто нет содержимого в DESCRIPTION). Ждём развития!)

klimenko-serj commented 10 years ago

Добавил поддержку блоб, пока самое основное. Пример работы:

(cl-fbclient:fb-with-database (db :path "/home/db/1.fdb") (cl-fbclient:fb-with-transaction (db tr) (let ((blb (first (cl-fbclient:fb-query "SELECT bt from T3" :tr tr :one-record)))) (cl-fbclient:fb-blob-open blb) (unwind-protect (cl-fbclient:fb-blob-read blb 1024) (cl-fbclient:fb-blob-close blb)))))

(cffi:foreign-string-to-lisp *)

поле bt - Блоб, в котором лежит текст. fb-blob-read - возвращает cffi-указатель на массив :char

проверьте - отпишитесь.

LinkFly commented 10 years ago

Ок, видимо завтра займусь.

LinkFly commented 10 years ago

Необходимо автоматическое преобразование BLOB'ов.

Для интеграции библиотеки в проект мне необходимо автоматическое преобразование BLOB'ов в строку. Я этого добился пропатчив ф-ию get-var-val-by-type, а именно я поменял код простого создание BLOB'ов:


(cond 
  ...
  ((eq type ':blob)
       (make-instance 'fb-blob ...))

на этот:

((eq type ':blob)
      (let ((blob (make-instance 'fb-blob ...)
        (when *blob-convertor* 
          (funcall *blob-convertor* blob))))
                id))

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

Вот полный патч:


(defparameter +blob-to-nil+ (lambda (blob) (declare (ignore blob)) nil))
(defparameter +blob-to-string+ (lambda (blb)
                                 (cl-fbclient:fb-blob-open blb)
                                 (unwind-protect
                                     (cffi:foreign-string-to-lisp (cl-fbclient:fb-blob-read blb 1024))
                                   (cl-fbclient:fb-blob-close blb))))
(defparameter *blob-convertor* +blob-to-string+)
(defun get-var-val-by-type (stmt index type)
  (let ((xsqlda* (xsqlda-output* stmt)))
    (cond  ; case??
     ((eq type ':text)
      (cffi:foreign-string-to-lisp (xsqlda-get-var-val xsqlda* index)))
     ((eq type ':varying) 
      (cffi:foreign-string-to-lisp  (inc-pointer (xsqlda-get-var-val xsqlda* index) 2)
                                    :count (mem-aref (xsqlda-get-var-val xsqlda* index)
                                                     :short)))
     ((eq type ':timestamp)
      (convert-timestamp-alist
       (fb-timestamp2datetime-list (mem-aptr (xsqlda-get-var-val xsqlda* index) 
                                             '(:struct isc_timestamp)))))
     ((eq type ':decimal)
      (* (cffi:mem-aref (xsqlda-get-var-val xsqlda* index) :long) 
         (pow-10 (xsqlda-get-var-sqlscale xsqlda* index))))
     ((eq type ':blob)
      (let ((blob (make-instance 'fb-blob 
                                 :fb-tr (fb-tr stmt) 
                                 :id (let ((id (foreign-alloc '(:struct ISC_QUAD))))
                                       (setf (mem-aref id '(:struct ISC_QUAD))
                                             (mem-aref (xsqlda-get-var-val xsqlda* index) 
                                                       '(:struct ISC_QUAD)))
                                       id))))
        (when *blob-convertor* 
          (funcall *blob-convertor* blob)))) ; TODO: Test it!
     (T (cffi:mem-aref (xsqlda-get-var-val xsqlda* index) type)))))
;;+ *blob-convertor* +blob-to-nil+ +blob-to-string+ в экспорт
LinkFly commented 10 years ago

Вместо 1024 необходимо видимо получать реальный размер BLOB-поля, что имеет отношение к чтению метаинформации (https://github.com/klimenko-serj/cl-fbclient/issues/9)

LinkFly commented 10 years ago

Т.е. в моём патче значение 1024 (при чтении BLOB'a) используется временно и неправомерно.

klimenko-serj commented 10 years ago

Добавил:

Проверяйте.

Вопрос: Какая метаинформация вам необходима? (Размер в байтах, имя поля, тип поля можно получить не только для таблицы, а и для запроса.)

12 декабря 2013 г., 17:48 пользователь Sergey Katrevich < notifications@github.com> написал:

Т.е. в моём патче значение 1024 (при чтении BLOB'a) используется временно и неправомерно.

Reply to this email directly or view it on GitHubhttps://github.com/klimenko-serj/cl-fbclient/issues/8#issuecomment-30433708 .