BUDDEN> (let1 *firebird-trace* t
(fse user_group.* from user_group M_INNER_JOIN(user_group,app_user);
))
select user_group.* from user_group inner join app_user as app_user on app_user.Id = user_group.REF_USER
NIL
#("REF_USER" "REF_GROUP" "RANK")
> (float (/ (length "user_group.* from user_group inner join app_user as app_user on app_user.Id = user_group.REF_USER")
(length "user_group.* from user_group M_INNER_JOIN(user_group,app_user);")))
1.6031746031746033
Общая идея: M_INNER_JOIN берёт из словаря данные о ссылках между таблицами и строит соответствующий фрагмент inner join. Про fse я уже писал раньше - это symbol-readmacro (в отличие от обычно используемого в лиспе readmacro-character), который читает лексемы SQL (в данном случае файрбёрда, а другие мне пока не нужны) до точки с запятой и выполняет считанное. В данном примере код ужался в 1.6 раза. Эту штуку я недавно написал, ещё не уверен в её совершенстве, но, видимо, буду пользоваться ежедневно и интенсивно. Давно замышлял такое сделать.
Вот исходники:
(def-firebird-macro-1 M_INNER_JOIN (from to &optional to-alias)
"to может быть именем таблицы или ref_alias-ом"
(proga
(let from-src (expand-m-alias from))
(multiple-value-bind (fld dst dst-alias) (find-field-ref from-src to))
(assert fld () "M_INNER_JOIN: can't find reference ~A in (~A as ~A)" to from-src from)
(let dst-alias-2 (or to-alias dst-alias dst))
(let dst-alias-introduction
(if (db-identifier-equal dst dst-alias) dst (fbody M_AS(~~dst,~~dst-alias-2)^)))
(fbody inner join ~~dst-alias-introduction on ~~(FB-поле dst-alias-2 "Id") = ~~(FB-поле from fld) ^)
))
Исходник FSEL приводить не буду, т.к. слишком сложно. Чтобы была ясна идея symbol-readmacro, вот более простой пример:
(defun here-document-readmacro-reader (stream symbol)
(declare (ignore symbol))
(budden-tools:it-is-a-car-symbol-readmacro
(let1 terminator (string (read-preserving-whitespace stream))
(read-char stream)
(text-up-to-terminator-lexer stream terminator)
)))
(setf (symbol-readmacro (intern "HERE-DOCUMENT" :budden)) #'here-document-readmacro-reader)
> (here-document $$ eqasdfdsf " ' $$)
"eqasdfdsf \" ' "