Язык Tcl ( Tool Command Language ) был придуман
John Ousterhout [1]. На самом деле Tcl это собственно сам язык и интерпретатор.
Это структурный язык использующий три типа данных: строки, списки и массивы. Работая на
нем можно использовать регулярные выражения [2], сторонние библиотеки расширения и
Tk, пакет для создания графических приложений на Tcl.
СУБД MySQL очень популярный сервер баз данных
в сообществе свободно распространяемого программного обеспечения, который не нуждается в
представлении.
MySQLTcl это библиотека для языка Tcl с помощью
которой можно работать с СУБД MySQL из скриптов, написанных на языке Tcl. В настоящее время
авторами и разработчиками этой библиотеки являются Paolo Brutti (Paolo.Bruti at tlsoft.it),
Tobias Ritzau (tobri at ida.liu.se) и Artur Trzewick (mail at xdobry.de).
_________________ _________________ _________________
|
Установка библиотеки MySQLTcl
Если Ваша Linux или *BSD система поддерживает пакеты ( напрмер RPM или DEB ) или порты как
Crux Linux или FreeBSD,
Вы можете использовать их для установки библиотеки MySQLTcl и пропустить этот раздел.
Если это не так или Вы просто предпочитаете устанавливать все "руками", я продемонстрирую Вам
как это делал сам. Вы можете использовать это как инструкцию, но не как пошаговое руководство
установки. Используя bash дистрибутива Linux Mandrake
версии 9.2 делаем следующее:
$ ./configure --with-mysql-lib=/usr/lib
$ make
$ make install
|
Если что-то происходит не так во время шага "configure", информация об ошибках послужит
помощью для их исправления. Обычно проблемная ситуация заключается в следующем - скрипт
configure не находит определенные каталоги или файлы. Исправить это можно передавая
скрипту пути к этим файлам или каталогам в качестве параметров. Например, устанавливая
MySQLTcl на FreeBSD 5.0 я использовал следующие опции:
$ export CPP=/usr/bin/cpp
$ ./configure --with-tcl=/usr/lib/local/tcl8.3
--with-tclinclude=/usr/local/include/tcl8.3
--with-mysql-include=/usr/local/include/mysql
--with-mysql-lib=/usr/local/lib/mysql
$ make
$ make install
|
Надеюсь Вы заметили, что в этом примере используется Tcl версии 8.3, кроме того - версия
библиотеки MySQLTcl 2.15, а сервера MySQL 3.23.54.
Основы Tcl
В этом разделе рассмотрим основы Tcl для тех, кому интересна данная заметка, но они не
знакомы с ним. Если Вы программируете на Tcl - можете пропустить этот раздел.
Вы можете потренироваться на этих примерах из оболочки Tcl (tclsh).
Переменные. Команда и подстановка переменных.
Переменные Tcl создаются с помощью команды set. Рассмотрим несколько примеров:
% set address {Edison Avenue, 83}
Edison Avenue, 83
% set zip_code 48631
48631
|
В этих двух примерах мы создали две переменные - address и zip_code, и присвоили им значения
Edison Avenue, 83 и 48361, которые имеют тип string. Обратите внимание на то,
что при присвоении переменной address значение мы использовали фигурные скобки потому, что в
нем есть пробел. Получить значения переменных можно командой set:
% set address
Edison Avenue, 83
% set zip_code
48631
Чтобы вывести значение переменной address на экран воспользуемся командой puts:
% puts stdout [set address]
Edison Avenue, 83
Параметр stdout передаваемый команде puts служит для указания вывода
в стандартный поток вывода - на экран. Второй передаваемый параметр команде
puts это [set address]. Квадратные скобки указывают интерпретатору
Tcl, что это другая команда языка Tcl, которая должна быть выполнена перед командой
puts - это называется подстановка команд. То же самое можно сделать следующим
образом:
% puts stdout $address
Edison Avenue, 83
В этом примере мы выполнили подстановку переменной: символ $ перед переменной
указывает на это.
В предыдущем примере мы выяснили, что используя фигурные скобки можно собрать слова
в строки. Другая возможность сделать то же самое - использование кавычек ( символ " ).
Тем не менее, эти два способа ведут себя по-разному. Посмотрим на примере:
% puts stdout "the zip code is [set address]"
the zip code is 48631
% puts stdout "the zip code is $address"
the zip code is 48631
% puts stdout {the zip code is [set address]}
the zip code is [set address]
% puts stdout {the zip code is $address}
the zip code is $address
Здесь видно, что при использовании фигурных скобок подстановки переменных не происходит,
но происходит при использовании кавычек.
Удалить переменные можно командой unset:
% unset address
% set address
can't read "address": no such variable
% unset zip_code
% set zip_code
can't read "zip_code": no such variable
Строки в Tcl
Строки являются одним из трех основных типов данных в Tcl. Строка - это набор символов.
Строка создается с помощью команды set.
% set surname Westmoreland
Westmoreland
% set number 46.625
46.625
Обе переменные - surname и number имеют тип строка. Работать с переменными этого
типа можно командой string. Синтаксис этой команды следующий - string
операция значение другие_аргументы. Поясним примерами:
% string length $surname
12
% set surname [string range $surname 0 3]
West
% puts stdout $surname
West
% string tolower $surname
west
В отличие от Java или Pascal Tcl не очень строгий язык программирования. Следующий пример
демонстрирует это:
% set number [expr $number + 24.5]
70.125
% string range $number 2 5
.125
С помощью команды expr мы увеличили значение переменной number на 24.5.
После этого мы представили переменную number строковой и с помощью команды string
вывели последние четыре символа.
Списки в Tcl
Списки в Tcl являются разновидностью строк, которые разделены пробелом и интерпретируется
соответственное по-своему.
% set friends_list {Fany John Lisa Jack Michael}
Fany John Lisa Jack Michael
% set friends_list [string tolower $friends_list]
fany john lisa jack michael
% set friends_list
fany john lisa jack michael
В Tcl существует набор команд для работы со строками. Рассмотрим несколько примеров:
% lindex 2 $friends_list
lisa
% lrange $friends_list 2 4
lisa jack michael
% set friends_list [lsort -ascii $friends_list]
fany jack john lisa michael
% set friends_list
fany jack john lisa michael
% set friends_list [linsert $friends_list 2 Peter]
fany jack Peter john lisa michael
% string toupper $friends_list
FANY JACK PETER JOHN LISA MICHAEL
Из последнего примера видно, что строки и списки имеют одинаковую структуру.
Массивы в Tcl
Массив можно рассматривать особым видом списка с индексом в качестве которого
выступает переменная типа "строка". Рассмотрим пример создания массива:
% set phone_numbers(fany) 629
629
% set phone_numbers(michael) 513
513
% set phone_numbers(john) 286
286
Получить значение из массива можно используя команду set как и в предыдущем примере,
индекс заключается в круглые скобки.
% set $phone_numers(michael)
513
Информацию о массиве можно получить с помощью команды array. Рассмотрим несколько
примеров использования данной команды:
% array size phone_numbers
3
% array names phone_numbers
fany john michael
Подключение к базе данных
Для того чтобы выполнять запросы к базе данных из скриптов Tcl сначала надо установить
соединение с сервером баз данных. В этой части заметки мы рассмотрим этот вопрос, а также
обработку ошибок, которые могут возникнуть в процессе соединения.
Соединение с сервером бд
Рассмотрим пример подключения к серверу MySQL из Tcl скрипта:
0: #!/usr/bin/tclsh8.4
1:
2: package require mysqltcl
3: global mysqlstatus
4:
5: set port {3306}
6: set host {127.0.0.1}
7: set user {john_smith}
8: set password {jsmith_password}
9:
10: set mysql_handler [mysqlconnect -host $host
-port $port -user $user -password $password]
11:
12: mysqlclose $mysql_handler
Обратите внимание на левую колонку цифр - они не являются частью нашего скрипта, таким образом
мы просто пронумеровали строки. Также, в зависимости от используемого вами дистрибутива
Linux, вам возможно придется поменять строку #0, указывающую путь к Tcl shell.
Строка #0 указывает shell'у, что данный файл является скриптом Tcl и указывает где искать
интерпретатор Tcl.
В строке #2 стоит указание интерпретатору использовать библиотеку MySQLTcl. Например в строке
#10 вызывается команда mysqlconnect, если бы мы не указали в строке #2 библиотеку, тогда
при вызове данной команды интерпретатор выдал бы ошибку "команда не найдена" ( command not found ).
В строках #5 и #6 инициализируются переменные port и host. В нашем примере port инициализируется
значением 3306 ( по умолчанию MySQL прослушивает этот порт ), а host - адресом локального
компьютера.
В строках #7 и #8 инициализируются переменные user и password.
В строке #10 устанавливается само соединение и handler сохраняется в переменной
mysql_handler, его используют для запросов к бд и закрытия соединения, как показано
в строке #12.
Обработка ошибок
В предыдущей части мы не рассмотрели строку #3. Сделаем это сейчас.
Выполнение команд библиотеки MySQLTcl может вызывать ошибки. Если мы не поймаем эту ошибку,
скрипт может прекратить свою работу. Поменяем немного наш скрипт следующим образом:
10: if [catch {mysqlconnect -host $host -port $port
-user $user -password $password} mysql_handler] {
11: puts stderr {error, the database connection could not be established}
12: exit
13: } else {
14: mysqlclose mysql_handler
15: }
Если команда set mysql_handler [mysqlconnect -host $host... вызовет ошибку - она будет
перехвачена командой catch. Команда catch возвращает 1 в случае возникновения
ошибки и 0 в противоположном.
В случае возникновения ошибки сообщение выводится в стандартный поток вывода, в нашем
случае это экран. Подобные ошибки возникают в разных обстоятельствах - неправильный пароль,
хост, порт и т.д. В подобном случае более подробное описание ошибки будет полезным.
В строке #3 мы объявили глобальную переменную mysqlstatus. Глобальная переменная
доступна в любом месте Tcl скрипта. Библиотека MySQLTcl создает глобальный массив
mysqlstatus, в котором содержатся следующие элементы:
| элемент |
значение |
| code |
Если ошибка не произошла mysqlstatus(code) равен нулю, в противном услучае
устанавливается в код ошибки сервера MySQL. Если ошибка возникла, но не является ошибкой
MySQL, то значение mysqlstatus(code) устанавливается в -1.
Значение mysqlstatus(code) обновляется после каждого использования команды библиотеки
MySQLTcl.
|
| command |
Команда библиотеки MySQLTcl, выполнение которой породило ошибку, сохраняется в
mysqlstatus(command).
Значение mysqlstatus(command) обновляется после каждой команды вызвавшей ошибку,
другими словами - mysqlstatus(command) не обновляется после успешной команды.
|
| message |
Значение mysqltcl(message) обновляется после каждой команды вызвавшей ошибку
и заполняется сообщением об ошибке. Также как и mysqlstatus(command),
mysqlstatus(message) не обновляется после успешной команды.
|
Существует еще один элемент в глобальном массиве mysqlstatus, который не связан с
обработкой ошибок:
| элемент |
значение |
| nullvalue |
Строка, используемая для значения null как результата выполнения SQL запроса. По умолчанию
используется пустая строка; musqlstatus(nullvalue) может быть установлена в любое
строковое значение.
|
Таким образом, используя глобальный массив mysqlstatus, предыдущий код можно переписать
так, чтобы было понятно что произошло в случае установления соединения с сервером бд:
10: catch {mysqlconnect -host $host -port $port
-user $user -password $password} mysql_handler
11: if {$mysqltatus(code) != 0} {
12: puts stderr $mysqlstatus(message)
13: } else {
14: mysqlclose mysql_handler
15: }
Глобальный массив mysqlstatus можно использовать для обработки большего числа ошибок,
не только при установлении соединения с бд.
Основные команды библиотеки MySQLTcl
В этой части рассмотрим основные команды библиотеки MySQLTcl и некоторые примеры их
использования. Полную информацию по данному вопросу смотрите на man странице MySQLTcl.
Сначала приведем таблицу с данными командами. Параметры подчеркнуты. Если параметр стоит между
"?" - он опциональный, символ "|" обозначает "или".
|
команда
|
краткое описание
|
|
mysqlconnect ?option value ...?
|
подключение к бд; возвращает handler, который необходимо использовать в других командах mysqltcl
|
|
mysqluse handle dbname
|
ассоциирует MySQL handler с определенной бд
|
|
mysqsel handle sql_statement ?-list | -flatlist?
|
отправка SQL команды в бд
|
|
mysqlexec handle sql_statement
|
отправка не_select SQL команды в бд
|
|
mysqlclose handle
|
закрытие соединения с бд
|
mysqlconnect
Эту команду мы уже обсуждали в разделе "Соединение с сервером бд", но есть один момент,
который мы не затронули - параметр -db, он нужен для привязки определенной бд для
последующего использования. Посмотрим пример:
% set mysql_handler [mysqlconnect -h 127.0.0.1 -p 3306 \
-user john_smith -password jsmith_password -db jsmith_database]
В этом случае при последующем использовании mysql_handler запросы будут будут
направлены в бд jsmith_database.
( Пожалуйста, обратите внимание на символы \, они не являются частью команды; они показывают,
что команда продолжается на следующей строке ).
mysqluse
Команда служит для смены бд ассоциированной с handler'ом, бд указывается первым параметром.
mysqlsel
С помощью данной команды посылается SQL select запрос в бд. если параметр sql_statement
не является SQL select запросом - произойдет ошибка.
Можно использовать в этой команде третий ( опциональный ) параметр - list или flat_list.
Посмотрим на примере что происходит с выводом, при использовании этого параметра. Предположим
в бд есть таблица people:
| id |
first_name |
last_ name |
phone |
| 26 |
Karl |
Bauer |
8245 |
| 47 |
James |
Brooks |
1093 |
| 61 |
Roberto |
Castro Portela |
6507 |
С помощью команды mysqlsel посылаем SQL запрос в бд:
% mysqlsel $mysql_handler {select first_name, last_name from people order by id asc} -list
{Karl Bauer} {James Brooks} {Roberto {Castro Portela}}
% mysqlsel $mysql_handler {select first_name, last_name from people order by id asc} -flatlist
Karl Bauer James Brooks Roberto {Castro Portela}
В первом случае (-list parameter) команда возвращает список, элементы которого списки.
Во втором случае (-flatlist parameter) команда возвращает список, элементы которого
идут все вместе.
Что произойдет если использовать команду mysqlsel без третьего параметра? В этом случае
результатом работы команды будет число строк, возвращенных запросом:
% mysqlsel $mysql_handler {select first_name, last_name from people order by id asc}
3
mysqlexec
С помощью команды mysqlexec можно послать не_select SQL запрос в бд. Если с помощью
этой команды вы пошлете select SQL запрос - ошибки не произойдет, но и ничего не будет сделано.
Посмотрим еще раз на предыдущий пример:
% mysqlexec $mysql_handler {delete from people where id=26}
1
% mysqlsel $mysql_handler {select first_name, last_name, phone from people order by id asc} -list
{James Brooks 1093} {Roberto {Castro Portela} 6507}
% mysqlexec $mysql_handler \
{insert into people (id, first_name, last_name, phone) values (58, "Carla", "di Bella", 8925)}
1
% mysqlsel $mysql_handler {select first_name, last_name, phone from people order by id asc} -list
{James Brooks 1093} {Carla {di Bella} 8925} {Roberto {Castro Portela} 6507}
Естественно SQL запросы отличные от delete или insert могут быть посланы с помощью этой команды.
Например update данных:
% mysqlexec $mysql_handler {update people set phone=3749 where first_name="James"}
1
% mysqlsel $mysql_handler {select first_name, last_name, phone from people order by id asc} -list
{James Brooks 3749} {Carla {di Bella} 8925} {Roberto {Castro Portela} 6507}
Результатом работы команды mysqlexec является число строк, которые были обработаны
не_select SQL запросом.
mysqlclose
Команда mysqlclose закрывает соединение с бд. Параметром этой команды является
MySQL handler соединения, которое мы хотим закрыть.
Другие команды библиотеки MySQLTcl
Набор команд библиотеки MySQLTcl не ограничивается рассмотренными выше - есть команды для
получения информации о бд, обработки строк для использования в запросах, создания вложенных
запросов. Правильным местом для изучения библиотеки MySQLTcl является ее man страница.
Ссылки
[1] a slightly skeptical view on John K. Ousterhout and Tcl:
http://www.softpanorama.org/People/Ousterhout/index.shtml>
[2] Руководство по регулярным выражениям Tcl:
http://www.mapfree.com/sbf/tcl/book/select/Html/7.html>
TclTutor - бесплатное приложение для изучения Tcl:
http://www.msen.com/~clif/TclTutor.html>
Документация MySQL в разных форматах ( HTML, PDF... ):
http://www.mysql.com/documentation/index.html>
www.linuxfocus.org
 |