Common Lisp, MySQL and openSUSE
С недавних пор позволил себе наглость писать на Common Lisp’е (CL) на работе. Добрался до скриптов, которые до меня были написанны на perl’e, а точнее – понадобилось кое-что в них добавить, и я решил, что переписать их на CL будет и быстрее и полезнее для меня. Скажу сразу, что нет ничего, что можно сделать на CL, но нельзя, к примеру, на perl или python. Другим будет лишь подход к решению, несмотря на то, что, к примеру, на python тоже можно очень не плохо писать в функциональном стиле. Именно из-за этого подхода программисты CL находят его использование столь интересным, гибким и выразительным.
В этом посте я постараюсь показать, что в использование CL нет ничего сверхестественного. Дополнительные библиотеки, скачиваемые из интернета, стандартная библиотека языка… постораемся сделать что-то практическое.
Итак, я использую clisp, и quicklisp в качестве library manager’a. На его домашней странице вы найдете подробное руководство по установке и использовании.
Для начала найдем все библиотеки, имена которых содержат “mysql”:
> (ql:system-apropos "mysql") #SYSTEM cl-mysql / cl-mysql-20120208-git / quicklisp 2014-08-26> #SYSTEM cl-mysql-test / cl-mysql-20120208-git / quicklisp 2014-08-26> #SYSTEM clsql-mysql / clsql-20140713-git / quicklisp 2014-08-26> #SYSTEM dbd-mysql / cl-dbi-20140826-git / quicklisp 2014-08-26>
Нам нужна cl-mysql. Устанавливаем:
> (ql:quickload "cl-mysql")
To load "cl-mysql":
Install 5 Quicklisp releases:
alexandria babel cffi cl-mysql trivial-features
; Fetching #
; 8.09KB
==================================================
8,284 bytes in 0.00 seconds (8736.33KB/sec)
; Fetching #
; 238.72KB
==================================================
244,450 bytes in 0.54 seconds (438.44KB/sec)
; Fetching #
; 48.70KB
==================================================
49,872 bytes in 0.03 seconds (1763.46KB/sec)
; Fetching #
; 207.21KB
==================================================
212,186 bytes in 0.37 seconds (567.45KB/sec)
; Fetching #
; 24.96KB
==================================================
25,561 bytes in 0.09 seconds (268.06KB/sec)
; Loading "cl-mysql"
[package alexandria.0.dev]........................
[package babel-encodings].........................
[package babel]...................................
[package cffi-sys]................................
[package cffi]....................................
[package cffi-features]...........................
[package com.hackinghat.cl-mysql-system]..
*** - Unable to load foreign library (LIBMYSQLCLIENT).
FFI:OPEN-FOREIGN-LIBRARY: Cannot open library "libmysqlclient_r.so":
"libmysqlclient_r.so: cannot open shared object file: No such file or directory"
The following restarts are available:
RETRY :R1 Try loading the foreign library again.
USE-VALUE :R2 Use another library instead.
SKIP :R3 skip 75 75 (USE-FOREIGN-LIBRARY LIBMYSQLCLIENT)-4
RETRY :R4 retry 75 75 (USE-FOREIGN-LIBRARY LIBMYSQLCLIENT)-4
STOP :R5 stop loading file /home/anaumov/.cache/common-lisp/clisp-2.49- \
unix-x64/home/anaumov/quicklisp/dists/quicklisp/software/cl-mysql-20120208-git/system.fas
TRY-RECOMPILING :R6 Recompile system and try loading it again
RETRY :R7 Retry loading FASL for #.
ACCEPT :R8 Continue, treating loading FASL for # as having been successful.
ABORT :R9 Give up on "cl-mysql"
ABORT :R10 Abort main loop
Break 1 CL-MYSQL-SYSTEM[4]>
Знакомая всем пользователям Linux ошибка отсутствия необходимой библиотеки. Clisp-интерпретатор предлагает несколько вариантов дальнейшей работы. Мы продолжим работу с ним, но для начала нам нужно установить rpm-пакет (в другой консоли), содержащий файл libmysqlclient_r.so:
> sudo zypper in libmysqlclient_r18 > rpm -ql libmysqlclient_r18 /usr/lib64/libmysqlclient_r.so.18 /usr/lib64/libmysqlclient_r.so.18.0.0 > cd /usr/lib64 # ln -s libmysqlclient.so.18.0.0 libmysqlclient_r.so
Последняя команда создает линк из-за несоответствия имени библиотеки. После этого возвращаемся в clisp (оставили его открытым?) и предлагаем попробывать еще раз: RETRY. После этого уснановка продолжается. Проверим все ли в порядке, и можем ли мы теперь работать с базой данных:
> (use-package :cl-mysql) T > (cl-mysql:connect :host "127.0.0.1" :database "centreon" :user "user" :password "foobar") #COM.HACKINGHAT.CL-MYSQL-SYSTEM:CONNECTION-POOL #x0003345319D8
Connect выводит адрес созданного пула – объекта cl-mysql пакета. Его синтаксис, кстати, один в один напоминает аналог из sqlalchemy. Синтаксис позволяет использовать язык SQL в качестве параметра cl-mysql:query, поэтому тут тоже ничего нового. Рассмотрим один пример.
(defun views-columns() (cl-mysql:connect :host "127.0.0.1" :database "information_schema" :user "user" :password "foobar") (loop for i in (car (car (cl-mysql:query "show columns from VIEW"))) do (format t "~A~%" i)))
Заголовок (шапку таблицы) мы получаем в виде еще одного cписка. Я обрезал его при помощи car.
Вот что выдаст функция views-columns:
(TABLE_CATALOG varchar(512) YES NIL NIL NIL) (TABLE_SCHEMA varchar(64) NO NIL NIL NIL) (TABLE_NAME varchar(64) NO NIL NIL NIL) (VIEW_DEFINITION longtext NO NIL NIL NIL) (CHECK_OPTION varchar(8) NO NIL NIL NIL) (IS_UPDATABLE varchar(3) NO NIL NIL NIL) (DEFINER varchar(77) NO NIL NIL NIL) (SECURITY_TYPE varchar(7) NO NIL NIL NIL) (CHARACTER_SET_CLIENT varchar(32) NO NIL NIL NIL) (COLLATION_CONNECTION varchar(32) NO NIL NIL NIL)
Для сравнения вывод той же команды в mysql-интрепретаторе:
mysql> show columns from VIEWS; +----------------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------------+--------------+------+-----+---------+-------+ | TABLE_CATALOG | varchar(512) | YES | | NULL | | | TABLE_SCHEMA | varchar(64) | NO | | | | | TABLE_NAME | varchar(64) | NO | | | | | VIEW_DEFINITION | longtext | NO | | NULL | | | CHECK_OPTION | varchar(8) | NO | | | | | IS_UPDATABLE | varchar(3) | NO | | | | | DEFINER | varchar(77) | NO | | | | | SECURITY_TYPE | varchar(7) | NO | | | | | CHARACTER_SET_CLIENT | varchar(32) | NO | | | | | COLLATION_CONNECTION | varchar(32) | NO | | | | +----------------------+--------------+------+-----+---------+-------+ 10 rows in set (0.02 sec)
to be or not to be
Вопреки распространенному мнению, Lisp жив. Библиотеки, как мы только что убедились, для него есть, они поддерживаются, и их установка не вызывает никаких проблем. Синтаксис CL очень схож с python: cкобки вы перестанене замечать уже на следующий день его использования, а ориентироваться в коде будете по отступам.
Зачем Lisp, когда есть Python? Если кого-то до сих пор задается этим вопросом, загляните в статью Ерика Реймонда или, возможно, вас заинтересует мнение Ричарда Столлмана. Сам я далеко не специалист в Lisp, тем не менее программирование на CL помогает мне лучше писать функциональный код на, к примеру, том же python. Многие идеи, реализованные в Lisp полвека назад, только начинают сейчас включать в Java, в python они до сих пор реализованны частично.
leave a comment