LXF89:PostgreSQL
PonElA (обсуждение | вклад) (Новая: '''PostgreSQL. ЧАСТЬ 4: Интерфейсы''' :В институте им очень дорожили, так как :попутно он использовался для нек...) |
Lockal (обсуждение | вклад) м (восстановление кавычек в коде AWB) |
||
(не показаны 3 промежуточные версии 3 участников) | |||
Строка 1: | Строка 1: | ||
− | '''PostgreSQL | + | {{Цикл/PostgreSQL}} |
+ | '''История PostgreSQL''' Изучаем самый мощный из открытых серверов баз данных | ||
− | : | + | == Интерфейсы == |
− | + | ''ЧАСТЬ 4: Интерфейсы, как известно, бывают не только пользовательскими, но и программными. С первыми мы уже успели познакомиться, а сегодня '''Евгений Балдин''' расскажет, какие API существуют для доступа к PostgreSQL из различных языков программирования.'' | |
− | + | ||
− | + | ||
− | + | ||
− | = | + | <p align="right">''В институте им очень дорожили, так как<br>попутно он использовался для некоторых<br>уникальных экспериментов и как переводчик<br>при общении со Змеем Горынычем.''<br>'''(О Кощее Бессмертном)'''<br>'''«Понедельник начинается в субботу»'''</p> |
− | + | ||
− | + | Понятно, что любую базу данных, в принципе, можно заполнить вручную; правда, некоторые придется заполнять очень долго. СУБД – это просто хранилище, а для заполнения и доступа к хранилищу необходима инфраструктура, и эту инфраструктуру надо создавать. Вот такая она – жизнь. | |
− | + | Родной библиотекой для доступа к ''PostgreSQL'' является ''libpq''. Написана она на чистом C, что тоже не удивительно, так как это основной язык родной системы. Все остальные языки важны, но безусловно, вторичны. | |
− | + | ||
− | + | ||
− | + | ||
− | |||
− | |||
− | |||
− | |||
− | === | + | === libpq === |
+ | Чтобы общаться с базой данных, много функций не требуется: одна для открытия соединения, одна для посылки запроса, одна для получения ответа и одна для закрытия соединения. В реальности, конечно, все немного сложнее, но суть остается неизменной. | ||
− | + | ===== К вопросу о переносимости ===== | |
− | + | Библиотека ''libpq'' написана на чистом C, поэтому связь с ''PostgreSQL'' можно организовать практически везде, где можно найти ''gcc''. Мне как-то пришлось делать это для VAX/VMS – все решилось методом тыка, даже думать почти не потребовалось. Все данные – текст, поэтому вопрос бинарной совместимости платформ попросту отсутствует. | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | Передача информации о | + | ===== С чего начать ===== |
− | + | Чтобы воспользоваться вызовами ''libpq'', ее необходимо иметь в системе. В Debian (Sarge) для этого надо установить пакет ''PostgreSQL-dev'': | |
− | + | ||
− | + | <pre> | |
− | + | > sudo apt-get install postgresql-dev | |
− | + | </pre> | |
− | + | ||
− | Параметры передаются в форме | + | Для доступа к функциям ''libpq'' необходимо включить в исходный текст соответствующие заголовки: |
+ | |||
+ | <source lang="c"> | ||
+ | #include "libpq-fe.h" | ||
+ | </source> | ||
+ | |||
+ | Скрипт ''pg_config'' (''man pg_config'') позволяет получить информацию о том, куда помещаются include-файлы, библиотеки и тому подобное. Для сборки можно также использовать скрипт ''libpq3-config'' (''man libpq3-config'' – годится, естественно, только для ''libpq'' третьей версии), который заведомо есть в Debian (Sarge): | ||
+ | |||
+ | <source lang="bash"> | ||
+ | > #сборка программы | ||
+ | > gcc -o "бинарник" "исходник".c -I'pg_config --includedir' \ | ||
+ | -lpq '/usr/bin/libpq3-config' | ||
+ | > cat /usr/bin/libpq3-config | ||
+ | #!/bin/bash | ||
+ | echo -lssl -lcrypto -lkrb5 -lcrypt -lresolv -lnsl -lpthread | ||
+ | </source> | ||
+ | |||
+ | ''libpq3-config'' просто выводит список всех библиотек, от которых зависит ''libpq''. | ||
+ | |||
+ | |||
+ | ==== Открытие и закрытие соединения ==== | ||
+ | Даже открывать соединение с ''PostgreSQL'' можно двумя способами: | ||
+ | |||
+ | <source lang="c"> | ||
+ | //открыть соединение | ||
+ | PGconn *PQconnectdb(const char *conninfo); | ||
+ | //то же, но не блокируя программу | ||
+ | PGconn *PQconnectStart(const char *conninfo); | ||
+ | //проверка статуса соединения (после PQconnectStart) | ||
+ | PostgresPollingStatusType PQconnectPoll(PGconn *conn); | ||
+ | </source> | ||
+ | |||
+ | '''PQconnectdb''' – обычная функция, принимающая текстовую строку '''conninfo''', содержащую параметры для соединения с сервером, и возвращающая структуру типа '''PGconn''' с информацией о созданном соединении и успешности данной операции. В дальнейшем при передаче данных эта структура будет использоваться в качестве параметра. | ||
+ | |||
+ | Передача информации о сервере в качестве строки ('''conninfo''') позволяет не менять внешний интерфейс вызова в случае появления дополнительных параметров и легко добавлять дополнительные опции. Пример открытия соединения: | ||
+ | |||
+ | <source lang="c"> | ||
+ | const char *conninfo= "dbname = test host=localhost"; | ||
+ | PGconn *conn=PQconnectdb(conninfo); | ||
+ | if (PQstatus(conn) != CONNECTION_OK) { | ||
+ | fprintf(stderr, "Не удалось соединиться с базой данных: %s", | ||
+ | PQerrorMessage(conn)); | ||
+ | /*завершаем работу*/ …} | ||
+ | </source> | ||
+ | |||
+ | Параметры передаются в форме '''«ключевое слово»=«значение»'''. Пары разделяются обычным пробелом. Пробелы вокруг знака равенства можно опустить. Если необходимо передать значение с пробелами, то его необходимо заключить в одинарные кавычки ''''«составное» «значение»''''. Для передачи одинарной кавычки ее необходимо экранировать с помощью обратной косой черты '''\''''. При отсутствии какого-либо параметра в строке '''conninfo''' его значение берется из соответствующей переменной окружения, если таковая определена. Если нет, то при открытии соединения используется значение по умолчанию. | ||
Функции открытия соединения распознают следующие параметры и переменные окружения (кое-какие особенности опущены): | Функции открытия соединения распознают следующие параметры и переменные окружения (кое-какие особенности опущены): | ||
− | * '''host | + | |
− | * '''hostaddr''' Числовой адрес узла на котором находится PostgreSQL (альтернатива host). Соответствует переменной окружения PGHOSTADDR. Значение по умолчанию эквивалентно localhost. | + | * '''host''' DNS-имя узла, на котором находится сервер ''PostgreSQL''. Соответствует переменной окружения '''PGHOST'''. Значение по умолчанию: '''localhost'''. |
− | * '''port''' Номер порта, который | + | * '''hostaddr''' Числовой адрес узла, на котором находится ''PostgreSQL'' (альтернатива '''host'''). Соответствует переменной окружения '''PGHOSTADDR'''. Значение по умолчанию эквивалентно: '''localhost'''. |
− | * '''dbname''' Имя базы данных. Соответствует переменной окружения PGDATABASE. Значение по умолчанию совпадает с системной | + | * '''port''' Номер порта, который «слушает» '''POSTMASTER'''. Соответствует переменной окружения '''PGPORT'''. Значение по умолчанию обычно '''5432'''. |
− | * '''user''' Имя пользователя базы данных. Соответствует переменной окружения PGUSER. Значение по умолчанию совпадает с системной | + | * '''dbname''' Имя базы данных. Соответствует переменной окружения '''PGDATABASE'''. Значение по умолчанию совпадает с системной учетной записью пользователя. |
− | * '''password''' Поле пароля, если для аутентификации требуется пароль. Соответствует переменной окружения PGPASSWORD. Если аутентификация требуется, а поле | + | * '''user''' Имя пользователя базы данных. Соответствует переменной окружения '''PGUSER'''. Значение по умолчанию совпадает с системной учетной записью пользователя. |
− | * '''connect_timeout''' Устанавливает максимальное время ожидания соединения в секундах. С сервером и сетью всякое может случиться. Соответствует переменной окружения PGCONNECT_TIMEOUT. Значение по умолчанию равно 0, что означает | + | * '''password''' Поле пароля, если для аутентификации требуется пароль. Соответствует переменной окружения '''PGPASSWORD'''. Если аутентификация требуется, а поле не определено, то для доступа используются данные файла '''~/.pgpass'''. Переменная окружения '''PGPASSFILE''' может указать другой файл для проведения аутентификации. |
− | * '''options''' Опции, посылаемые непосредственно серверу, | + | * '''connect_timeout''' Устанавливает максимальное время ожидания соединения в секундах. С сервером и сетью всякое может случиться. Соответствует переменной окружения '''PGCONNECT_TIMEOUT'''. Значение по умолчанию равно '''0''', что означает бесконечное время ожидания. Не рекомендуется устанавливать значение ожидания меньше 2 секунд. |
+ | * '''options''' Опции, посылаемые непосредственно серверу, если таковые потребуются. Соответствует переменной окружения '''PGOPTIONS'''. | ||
* '''sslmode''' Определяет порядок действий при SSL-соединении. Принимает четыре возможных значения: | * '''sslmode''' Определяет порядок действий при SSL-соединении. Принимает четыре возможных значения: | ||
− | ** '''disable''' | + | ** '''disable''' – без шифрования |
− | ** '''allow''' | + | ** '''allow''' – сначала попробовать соединиться без шифрования, а в случае неудачи постараться установить защищенное соединение, |
− | ** '''prefer''' | + | ** '''prefer''' – сначала попробовать установить защищенное соединение, а в случае неудачи повторить соединение без шифрования, |
− | ** '''require''' | + | ** '''require''' – выполнять только защищенное соединение. Соответствует переменной окружения '''PGSSLMODE'''. |
− | + | Значение по умолчанию: '''prefer'''. | |
− | * '''krbsrvname''' Имя Kerberos-сервиса. | + | * '''krbsrvname''' Имя Kerberos-сервиса. Используется для аутентификации с помощью Kerberos-5<ref> |
− | Kerberos промышленный стандарт для аутентификации и взаимодействия в условиях | + | Kerberos — промышленный стандарт для аутентификации и взаимодействия в условиях незащищенного окружения. Алгоритмы Kerberos основаны на шифровании с использованием симметричного криптографического ключа и требуют наличия доверенного агента. |
− | </ref>. Это совершенно отдельная тема | + | </ref>. Это совершенно отдельная тема, выходящая за рамки данной статьи. Соответствует переменной окружения '''PGKRBSRVNAME'''. |
+ | * '''PGDATESTYLE''' Переменная окружения, позволяющая установить представление времени и даты по умолчанию. Соответствует SQL-команде '''SET datestyle TO …''' | ||
+ | * '''PGTZ''' Переменная окружения, позволяющая установить текущий часовой пояс. Соответствует SQL-команде '''SET timezone TO …''' | ||
+ | * '''PGCLIENTENCODING''' Переменная окружения, позволяющая установить кодировку клиента. Соответствует SQL-команде '''SET client_encoding TO …''' | ||
− | + | Существует целый класс функций, которые позволяют получить информацию о соединении. За подробностями следует обратиться к документации, но для начала полезно знать о двух из них: | |
− | + | ||
− | + | ||
− | + | <source lang="c"> | |
− | + | ConnStatusType PQstatus(const PGconn *conn); | |
− | + | char *PQerrorMessage(const PGconn *conn); | |
− | + | </source> | |
− | + | '''PQstatus''' возвращает информацию о том, как прошло соединение. Интересны состояния '''CONNECTION_OK''' – все хорошо и '''CONNECTION_BAD''' – ничего не вышло. Функция '''PQerrorMessage''' позволяет получить текстовую строку с описанием последней возникшей проблемы. | |
− | + | ||
− | + | ||
− | + | ||
− | + | Для того, чтобы разорвать соединение, используется функция: | |
− | + | ||
− | + | <source lang="c"> | |
− | + | void PQfinish(PGconn *conn); | |
− | + | </source> | |
− | + | '''Внимание!''' Соединения следует закрывать сразу же, как только в них отпадает необходимость. Число соединений, которые поддерживает '''POSTMASTER''', ограничено – очень легко парализовать работу базы данных, просто открывая новые соединения. | |
− | |||
− | + | ==== SQL-запросы ==== | |
− | + | Что ж, до сервера мы уже «дозвонились», теперь пора с ним «поговорить». | |
+ | ===== Выполнение запросов ===== | ||
+ | Простейший способ выполнить ''SQL''-запрос – это воспользоваться функцией '''PQexec''': | ||
− | + | <source lang="c"> | |
+ | PGresult *PQexec(PGconn *conn, const char *command); | ||
+ | </source> | ||
− | '''Информация о состоянии запроса | + | В качестве параметров функции передается структура соединения '''conn''' и строка с ''SQL''-командой ''command''. Возвращается указатель на структуру типа '''PGresult''', где сохраняется информация, полученная от СУБД в ответ на запрос. При желании можно отсылать сразу несколько ''SQL''-команд в одном запросе, разделяя их ''';''' – точкой с запятой. В этом случае информация, сохраненная в структуре '''PGresult''', будет относиться только к последнему запросу. |
− | + | ||
− | На вход | + | {{Врезка |
− | + | |Заголовок=bond, но не Джеймс | |
− | + | |Содержание= | |
− | + | Лень писать все самому, но не лень изучать XML? Тогда ''BOND'' – это программа для Вас. Сайт проекта расположен по адресу: http://www.treshna.com/bond/. | |
− | + | ||
− | + | Рабочей частью пакета является исполняемый файл '''bondfrontend''', который осуществляет связь с базой данных и может «прикинуться» любой формой. Описание формы хранится в обычном XML-файле. Используемый диалект XML подробно описан в документации. | |
− | + | ||
− | + | [[Изображение:Img 89 87 1.jpg|thumb|center|300px|Формочки, XML (правда на заднем фоне и без подсветки) и связь с базой данных — это ''bond''.]] | |
− | + | ||
+ | История пакета насчитывает уже пять лет. Программа доступна по дуальной лицензии: GPL – для использования со свободным ПО и коммерческой – для использования в проприетарном. Существует версия и для Windows. | ||
+ | |||
+ | Перед инсталляцией ''bond'' следует внимательно прочесть README и установить все, что там перечислено. Сборка осуществляется с помощью ''scons'', который позиционируется как замена ''make'' с функциональностью ''automake/autoconf'' и синтаксисом от Python. Установка по умолчанию производится в '''/usr/local/'''. Для инсталляции (scons install) необходимы привилегии системного администратора. Затем можно приступать к чтению документации и изучению каталога examples. | ||
+ | |Ширина=320px}} | ||
+ | |||
+ | По умолчанию, каждый '''PQexec''' открывает отдельную транзакцию, если явно не начать ее с помощью команды '''BEGIN'''. В последнем случае транзакция будет продолжаться либо до '''COMMIT''', либо до '''ROLLBACK'''. | ||
+ | |||
+ | Есть более сложный вызов '''PQexecParams''', который позволяет передавать вызов и параметры к этому вызову раздельно. Таким образом исчезает необходимость самостоятельно формировать строку ''SQL''-команды и заботиться об экранировании данных, что важно в случае сохранения бинарных последовательностей. В качестве платы за соображения безопасности '''PQexecParams''' способен послать не более одной команды за раз. | ||
+ | |||
+ | В некоторых случаях для увеличения скорости выполнения часто встречающихся запросов полезно обратить внимание на пару функций '''PQprepare''' и '''PQexecPrepared'''. Эти команды эквивалентны своим ''SQL''-аналогам '''PREPARE''' и '''EXECUTE'''. Идея оптимизации состоит в том, что прежде чем выполнить запрос, ''PostgreSQL'' сначала анализирует его, затем планирует порядок действий и только потом, собственно, выполняет запрос. Первые два этапа для похожих запросов с разными условиями отбора можно выполнить заранее с помощью команды '''PREPARE'''. Затем, с помощью команды '''EXECUTE''', можно выполнять подобные уже подготовленные (prepared) запросы. | ||
+ | |||
+ | Все упомянутые выше команды работают с сервером БД синхронным образом, то есть посылают запрос и ждут ответа. Клиентское приложение на это время «засыпает». В ''libpq'' предусмотрен целый класс функций, предназначенный для асинхронных операций, не блокирующих клиентское приложение. Их применение усложняет код и логику программы, хотя все в пределах допустимого. С моей точки зрения, лучше организовать все так, чтобы время, использованное на ожидание результатов запроса, не влияло фатально на внешние процессы, и обеспечить бесперебойную работу сети и сервера базы данных. | ||
+ | |||
+ | ===== Информация о состоянии запроса ===== | ||
+ | После выполнения запроса всегда интересно узнать, каково его состояние: | ||
+ | |||
+ | <source lang="c"> | ||
+ | ExecStatusType PQresultStatus(const PGresult *res); | ||
+ | </source> | ||
+ | |||
+ | На вход подается структура '''PGresult''', создаваемая в результате работы '''PQexec'''-подобных функций, а на выходе получаем информацию о состоянии в виде числа, значение которого можно сравнить со следующими константами: | ||
+ | |||
+ | * '''PGRES_COMMAND_OK''' – все прошло хорошо (для запросов, которые не возвращают данные, например, '''INSERT'''), | ||
+ | * '''PGRES_TUPLES_OK''' – все прошло хорошо, плюс получены данные в ответ на запрос (для запросов типа '''SELECT''' или '''SHOW'''), | ||
+ | * '''PGRES_EMPTY_QUERY''' – строка запроса почему-то была пустой, | ||
+ | * '''PGRES_COPY_OUT''' – идет передача данных от сервера, | ||
+ | * '''PGRES_COPY_IN''' – идет передача данных на сервер, | ||
+ | * '''PGRES_BAD_RESPONSE''' – ошибка, ответ сервера не разборчив, | ||
+ | * '''PGRES_NONFATAL_ERROR''' – нефатальная ошибка: предупреждение (notice) или информация к сведению (warning), | ||
+ | * '''PGRES_FATAL_ERROR''' – при выполнении запроса произошла серьезная ошибка. | ||
Для получения более подробной информации об ошибке следует воспользоваться функцией | Для получения более подробной информации об ошибке следует воспользоваться функцией | ||
− | |||
− | |||
− | + | <source lang="c"> | |
− | + | char *PQresultErrorMessage(const PGresult *res); | |
− | + | </source> | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | При вызове этой функции в качестве результата будет сформирована строка с информацией об ошибке или пустая строка, если все прошло хорошо. | |
− | + | ||
− | + | ===== Получение данных ===== | |
+ | При получении данных предполагается, что статус запроса соответствует '''PGRES_TUPLES_OK'''. Теперь, если примерно известно, что хочется получить в результате запроса, то для получения данных достаточно четырех функций: | ||
− | + | <source lang="c"> | |
+ | int PQntuples(const PGresult *res); | ||
+ | int PQnfields(const PGresult *res); | ||
+ | char *PQgetvalue(const PGresult *res, | ||
+ | int row_number, int column_number); | ||
+ | int PQgetisnull(const PGresult *res, | ||
+ | int row_number, int column_number); | ||
+ | </source> | ||
− | ''' | + | Первые две функции являются информационными и позволяют узнать, сколько строк получено в результате запроса ('''PQntuples''') и сколько в каждой такой строке колонок ('''PQnfields'''). Возьмите на заметку, что 0 строк – это тоже хороший результат. |
− | + | Функция '''PQgetvalue''' позволяет получить доступ к данным. В качестве параметров кроме структуры соединения ('''res''') передается номер строки ('''column_number''') и номер колонки ('''column_number'''). Все данные возвращаются (как и посылаются) в виде текстовой строки, то есть перед употреблением их необходимо перевести в привычный формат. Например, в случае целых чисел можно воспользоваться функцией '''atoi'''. | |
− | + | ||
− | ''' | + | Следует помнить, что данные ''SQL'' могут иметь неопределенное значение ('''NULL'''). Если подобная возможность существует, то перед получением значения следует проверить, определено ли оно. '''Pqgetisnull''' позволяет разобраться с этой проблемой. По передаваемым параметрам эта функция эквивалентна '''PQgetvalue''', а в качестве результата возвращает '''1''', если значение не определено, и '''0''', если определено. |
− | ''' | + | Кроме упомянутых выше, существует целый ряд функций, позволяющих получить информацию о данных, как то: имя колонки ('''PQfname'''), размер передаваемых данных в байтах ('''PQgetlength''') и тому подобное. Для экранирования специальных символов при операции с бинарными или текстовыми данными есть набор сервисных функций '''PQescape*'''. |
− | + | ||
− | + | ||
− | === | + | ===== COPY ===== |
− | + | ''SQL''-команда '''COPY''' является расширением, специфичным для ''PostgreSQL''. Основное преимущество ''SQL'' – «все есть понятный текст», в некоторых случаях, когда надо передавать большие объемы данных, оборачивается недостатком. Функции '''PQputCopyData''' и '''PQgetCopyData''' в ряде случаев позволяют значительно ускорить передачу данных между сервером и клиентом. | |
− | ''' | + | ===== Асинхронные сигналы ===== |
+ | Стандартный ''SQL'' не предполагает взаимодействия разных пользователей, кроме как через изменение данных в таблицах. ''PostgreSQL'' позволяет посылать асинхронные сигналы с помощью команд '''LISTEN''' и '''NOTIFY'''. '''LISTEN "имя сигнала"''' передается серверу как обычная ''SQL''- команда. Если статус запроса становится равным '''PGRES_COMMAND_OK''', то это означает, что ранее был выполнен запрос '''NOTIFY "имя сигнала"'''. Если же инициализация сигнала ('''NOTIFY''') ожидается позже регистрации ('''LISTEN'''), то функция '''PQnotifies''' позволяет вновь проверить наличие сигнала после любого запроса. | ||
− | == | + | ===== Сборка «мусора» ===== |
− | + | «Мусор» убирать придется руками. Каждая функция типа '''PQexec''' создает объект типа '''PGresult'''. После того, как вся необходимая информация о результатах запроса получена, следует освободить память, занимаемую этим объектом с помощью команды: | |
− | + | <source lang="c"> | |
− | + | void PQclear(PGresult *res); | |
− | + | </source> | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | Если утечки памяти вас не волнуют, то можно этого и не делать. В этом случае следует побеспокоиться о том, почему вас не беспокоят утечки памяти? | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | ==== Большие объекты ==== | |
+ | Еще один способ сохранять неструктурированные данные в | ||
+ | ''PostgreSQL'' – это сохранять их в больших объектах ('''Large Objects'''). ''PostgreSQL'' предоставляет интерфейс, схожий с файловым интерфейсом Unix: '''open''' ('''lo_open'''), '''read''' ('''lo_read'''), '''write''' ('''lo_write'''), '''lseek''' ('''lo_lseek''') и так далее. Все '''lo_*''' команды работают со значениями, полученными из колонки с типом '''oid''' – это специальный тип данных, который является ссылкой на объект произвольного типа. То есть последовательность работы с большим объектом следующая: создается большой объект ('''lo_create'''). Далее возвращаемый '''lo_create''' указатель '''oid''' используется для записи данных в большой объект ('''lo_import/lo_write'''), а затем этот указатель вставляется в таблицу с помощью стандартных ''SQL''-операторов. Чтение происходит в обратном порядке ('''lo_export/lo_read'''). Все операции с большими объектами должны происходить внутри транзакции. | ||
− | + | Следует отметить, что необходимость интерфейса больших объектов на текущий момент не так уж и очевидна. Стандартными средствами в ''PostgreSQL'' можно сохранять бинарные данные размером вплоть до 1 Гб, что вполне может соперничать с максимальным размером для большого объекта (2 Гб). | |
− | + | ||
− | |||
− | * ''' | + | === ECPG === |
− | + | {| | |
+ | |- | ||
+ | | valign="top" | | ||
+ | Чтобы не отставать от коммерческих баз данных, ''PostgreSQL'' имеет свой собственный вариант «встроенного ''SQL''». Эта технология позволяет смешивать обычный язык C с ''SQL''-структурами, примерно следующим образом: | ||
+ | |||
+ | <source lang="c"> | ||
+ | // файл test.pgc | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | // структура для обработки ошибок | ||
+ | EXEC SQL include sqlca; | ||
+ | // реакция в случае ошибки/предупреждения | ||
+ | EXEC SQL whenever sqlwarning sqlprint; | ||
+ | EXEC SQL whenever sqlerror do ExitForError(); | ||
+ | void ExitForError() { | ||
+ | fprintf(stderr,"Все, конец - это фатально.\n"); | ||
+ | sqlprint(); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | int main(int argc, char **argv) | ||
+ | { | ||
+ | // определение переменных, чтобы их можно было использовать | ||
+ | // инструкциях ECPG | ||
+ | EXEC SQL BEGIN DECLARE SECTION; | ||
+ | const char *dbname = "test"; | ||
+ | const char *user = "baldin"; | ||
+ | VARCHAR FIO[128]; | ||
+ | VARCHAR NUMBER[128]; | ||
+ | EXEC SQL END DECLARE SECTION; | ||
+ | // соединение с базой данных | ||
+ | // внешние переменные предваряются двоеточием | ||
+ | EXEC SQL CONNECT TO :dbname USER :user; | ||
+ | // определение курсора через SELECT | ||
+ | EXEC SQL DECLARE mycursor CURSOR FOR | ||
+ | SELECT fio, number FROM fiodata,phonedata | ||
+ | WHERE fiodata.id=phonedata.id; | ||
+ | EXEC SQL open mycursor; | ||
+ | // чтение данных из курсора | ||
+ | EXEC SQL FETCH NEXT FROM mycursor INTO :FIO,:NUMBER; | ||
+ | while (sqlca.sqlcode == 0) { // не 0, если данные больше нет | ||
+ | printf("ФИО: %s номер: %s\n",FIO.arr,NUMBER.arr); | ||
+ | EXEC SQL FETCH NEXT FROM mycursor INTO :FIO, :NUMBER; | ||
+ | } | ||
+ | // разъединение с базой данных | ||
+ | EXEC SQL DISCONNECT; | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Все ''SQL''-команды начинаются с метки '''EXEC SQL'''. Она используется препроцессором ecpg как маркер для конструкций, подлежащих обработке. Внутри ''SQL''-команд можно использовать переменные C. Для этого перед ними необходимо поставить двоеточие «''':'''». | ||
+ | |||
+ | Для компиляции выше процитированного файла ('''test1.pgc''') необходимо выполнить следующие действия: | ||
+ | |||
+ | <pre> | ||
+ | > # установить ecpg | ||
+ | > sudo apt-get install libecpg-dev | ||
+ | > # запустить препроцессор | ||
+ | > ecpg test1.pgc | ||
+ | > # скомпилировать получившийся файл | ||
+ | > gcc -o test1 test1.c -I`pg_config --includedir` -lecpg | ||
+ | > # проверить работоспособность программы | ||
+ | > ./test1 | ||
+ | ФИО: Иванов И.П. номер: 555-32-23 | ||
+ | ФИО: Балдин Е.М. номер: 555-41-37 | ||
+ | ФИО: Балдин Е.М. номер: (+7)5559323919 | ||
+ | </pre> | ||
+ | |||
+ | Удобно это или нет – решайте сами. | ||
+ | | valign="top" | | ||
+ | {{Врезка|Заголовок=PostgreSQL в лицах: Сергей Копосов|Содержание= | ||
+ | [[Изображение:Img 89 89 1.jpg|thumb|left|100px]] | ||
+ | '''Визитка LXF:'''<br>Дипломированный физик. Профессиональный астроном. Участник программы Google Summer of Code 2006. Домашняя страница: http://lnfm1.sai.msu.ru/~math/.<br><br><br><br><br> | ||
+ | |||
+ | '''Евгений М. Балдин (ЕМБ): Что привлекло вас к разработке именно PostgreSQL?''' | ||
+ | |||
+ | '''Сергей Е. Копосов (СЕК):''' Вначале я познакомился с ''PostgreSQL'' как пользователь. Причины были следующие: необходимо было работать с большим астрономическим каталогом (2MASS), который содержал более 200 миллионов звезд. Здесь без базы данных не обойдешься. То, что выбран был именно ''PostgreSQL'', связано с тем, что рядом были люди<ref> | ||
+ | Множество «эти люди» включало Олега Бартунова. | ||
+ | </ref>, которые его уже использовали. | ||
+ | |||
+ | А дальше все пошло по нарастающей. Начав работать с ''PostgreSQL'', я вдруг обнаружил, что в нем не существует способов, с помощью которых можно было бы быстро искать объекты на сфере. В итоге это сподвигло меня на создание проекта Q3C (''QuadTreeCube'' http://q3c.sf.net). Процесс работы над ним потребовал выйти за рамки стандартного ''PostgreSQL''. Например, мне были необходимы bitmap-индексы, а Том Лэйн [Tom Lane] их тогда только реализовывал. Из-за этого мне пришлось перейти на работу c CVS-версией ''PostgreSQL''. Во время разработки Q3C мне удалось заметить несколько проблем со скоростью работы bitmap’ов, которые позже были исправлены Томом. | ||
+ | |||
+ | После интенсивной разработки Q3C я сильно «подсел» на списки рассылки ''pg-hackers'', ''pg-patches'', и я, в частности, написал несколько маленьких патчей для тех проблем в клиенте ''pSQL'', которые мне не нравились. Сначала автодополнение '''DROP~FUNCTION''', а потом улучшение работы ''pSQL'' c многострочными запросами. За последнее меня уже официально включили в список «Official contributors ''PostgreSQL''» – чем я несказанно горд [улыбка]. | ||
+ | |||
+ | '''ЕМБ: За что вас выбрали для участия в программе Summer of Code 2006, и чем эта эпопея закончилась?''' | ||
+ | |||
+ | '''СЕК:''' Тут сложно сказать. На самом деле, предложенных на Summer of Code проектов было не так уж и много, а мой проект не был ни чрезвычайно сложным, ни очень простым. Была общая подсказка от Тома, в каком направлении реализовывать проект. Сам проект был вполне естественным улучшением уже существующей функциональности ''PostgreSQL'', реализующей к тому же одну из маленьких недостающих частей стандарта SQL:2003. К тому же я уже был хотя бы минимально, но известен в сообществе ''pg-hackers''. | ||
+ | |||
+ | А закончилось все тем, что сейчас мой код по агрегатным функциям включен в CVS и будет в версии ''8.2 PostgreSQL''. За что, конечно, спасибо Тому Лэйну, который фиксировал и слегка корректировал код. | ||
+ | |||
+ | '''ЕМБ: Вы – профессиональный астроном, и, судя по списку проектов, вы активно работаете по основному профилю. ''PostgreSQL'' не отвлекает от вашей деятельности?''' | ||
+ | |||
+ | '''СЕК:''' Отвлекает. Очень. Поэтому пока я взял паузу в кодировании для ''PostgreSQL''. А дальше, поживем – увидим… | ||
+ | |Ширина=400px}} | ||
+ | |} | ||
+ | |||
+ | === Все остальное === | ||
+ | {{Врезка | ||
+ | |Заголовок=Азбука SQL: Г | ||
+ | |Содержание= | ||
+ | '''Управление доступом к данным'''<br> | ||
+ | Группа операторов ''SQL'', ответственных за дифференциацию пользователей путем предоставления и отмены привилегий, представляют из себя специализированный язык управления доступом к данным (Data Control Language). | ||
+ | |||
+ | Привилегии для работу с таблицами базы данных предоставляются пользователям с помощью команды: | ||
+ | |||
+ | <source lang="sql"> | ||
+ | GRANT «список привилегий» | ||
+ | ON TABLE «имя таблицы» [, …] | ||
+ | TO «пользователь» [, …] | ||
+ | </source> | ||
+ | |||
+ | Типы привилегий, которые можно предоставить пользователям: | ||
+ | * '''SELECT''' – разрешение на выполнение запроса на получение данных, | ||
+ | * '''INSERT''' – разрешение на добавление данных в таблицу, | ||
+ | * '''UPDATE''' – разрешение на изменение данных, | ||
+ | * '''DELETE''' – разрешение на удаление данных, | ||
+ | * '''REFERENCES''' – разрешение на создание ограничения по внешнему ключу, | ||
+ | * '''TRIGGER''' – разрешение на создание триггера, | ||
+ | * '''ALL''' – можно делать абсолютно все. | ||
+ | |||
+ | Эти привилегии можно дать только в случае, если таблица уже существует. На создание таблицы тоже надо иметь право: | ||
+ | |||
+ | <source lang="sql"> | ||
+ | GRANT CREATE | ||
+ | ON DATABASE «имя базы данных» [, …] | ||
+ | TO «пользователь» [, …] | ||
+ | </source> | ||
+ | |||
+ | Для отмены уже имеющихся привилегий используется команда: | ||
+ | |||
+ | <source lang="sql"> | ||
+ | REVOKE «список привилегий» | ||
+ | ON «имя таблицы» [, …] | ||
+ | FROM «пользователь» [, …] | ||
+ | </source> | ||
+ | |Ширина=350px}} | ||
+ | Эта статья называется «Интерфейсы», но большая часть ее посвящена только одному из них. Дело в том, что этот один является родным и наиболее полным, а все остальное – лишь подмножество. В простейшем случае все интерфейсы одинаковы: открыл соединение, послал запрос, обработал результаты, закрыл соединение. Также заметна энергосберегающая тенденция везде делать ровно один интерфейс на все типы СУБД. | ||
+ | |||
+ | ===== bash ===== | ||
+ | Да, да к ''bash'' тоже есть свой интерфейс, правда для этого надо наложить специальный патч. Возни, конечно, немало – зато к базе данных можно будет обращаться прямо из shell-скриптов. | ||
+ | |||
+ | Сайт проекта: http://www.psn.co.jp/postgresql/pgbash/index-e.html. | ||
+ | |||
+ | ===== Java ===== | ||
+ | Совершенно ожидаемо, что Java общается с ''PostgreSQL'' стандартным образом, а именно через JDBC. Поэтому, если вы знакомы с Java [а если нет – зачем вам использовать ее для доступа к ''PostgreSQL''? – прим. ред.], то достаточно добыть драйвер JDBC для ''PostgreSQL'', например отсюда: http://jdbc.postgresql.org/. В Debian (Sarge) достаточно набрать | ||
+ | |||
+ | <pre> | ||
+ | > sudo apt-get install libpgjava | ||
+ | </pre> | ||
+ | |||
и, прочитав README к пакету, приступить к работе. | и, прочитав README к пакету, приступить к работе. | ||
− | + | ===== Lisp ===== | |
− | + | Точнее, Common Lisp. Скорее всего, эти драйвера подойдут и для других диалектов: | |
− | + | ||
− | + | <pre> | |
− | Второй вариант является драйвером для единого интерфейса доступа к SQL-базам данных из Common Lisp | + | > sudo apt-get install cl-pg |
+ | #или | ||
+ | > sudo apt-get install cl-sql-postgresql | ||
+ | </pre> | ||
+ | |||
+ | Второй вариант является драйвером для единого интерфейса доступа к ''SQL''-базам данных из ''Common Lisp CLSQL'' (http://clsql.b9.com/). | ||
+ | |||
+ | ===== Perl ===== | ||
+ | Интерфейс для связи с ''PostgreSQL'' DBD-Pg используется в Perl через DBI<ref> | ||
+ | DBI — унифицированный интерфейс для доступа к данным. Подробнее об этом пакете можно узнать на CPAN: http://search.cpan.org/~timb/DBI-1.52/DBI.pm | ||
+ | </ref>. Все подробности доступны на CPAN: http://search.cpan.org/~dbdpg/dbd-pg/pg.pm. | ||
+ | |||
+ | <pre> | ||
+ | > sudo apt-get install libdbd-pg-perl | ||
+ | </pre> | ||
+ | |||
+ | DBD-Pg охватывает, фактически, все имеющиеся на сегодня возможности ''PostgreSQL'': от больших объектов ('''large objects''') до точек сохранения ('''savepoints'''). | ||
+ | |||
+ | ===== PHP ===== | ||
+ | О том как использовать ''PostgreSQL'' в PHP-проектах можно прочитать здесь: http://www.php.net/manual/en/ref.pgsql.php. Драйвер, скорее всего, тоже доступен в репозиториях дистрибутива: | ||
+ | |||
+ | <pre> | ||
+ | > sudo apt-get install php4-pgsql | ||
+ | </pre> | ||
− | + | Говорят, почти единственной причиной, по которой PHP-разработчики предпочитают ''MySQL'', является то, что раньше не было «родной» версии ''PostgreSQL'' под Windows. Начиная с ''PostgreSQL 8.0'', конкретно этот довод «против» уже не работает. | |
− | + | ||
− | + | ||
− | + | ===== Python ===== | |
− | + | Модуль для Python существует уже больше десяти лет. Подробности можно узнать здесь: http://www.druid.net/pygresql/. Установка модуля: | |
− | + | ||
− | + | <pre> | |
− | + | > sudo apt-get install python-pygresql | |
− | + | </pre> | |
− | + | ||
− | + | ===== Ruby ===== | |
− | + | Кое-что можно прочесть здесь: http://ruby.scripting.ca/postgres/. Установка происходит как обычно: | |
− | + | <pre> | |
− | + | > sudo apt-get install libdbd-pg-ruby | |
+ | </pre> | ||
− | == | + | ===== ODBC ===== |
− | + | Разработка драйвера идет на pgFoundry. Аскетичная страничка проекта доступна по адресу: http://pgfoundry.org/projects/psqlodbc/. Установка: | |
− | === | + | |
− | + | ||
− | + | <pre> | |
+ | > sudo apt-get install odbc-postgresql | ||
+ | </pre> | ||
− | |||
− | + | === Послесловие === | |
+ | Конечно, наш обзор интерфейсов к ''PostgreSQL'' нельзя назвать всеобъемлющим, но изложенных сведений вполне хватит для того, чтобы начать работать. Если впоследствии вам придет в голову идея «дописать что-то свое», не спешите хвататься за перо, то есть клавиатуру – советую сначала обратиться по адресу http://techdocs.postgresql.org/oresources.php и посмотреть, что уже сделано. | ||
− | |||
− | + | ---- | |
− | <references /> | + | <references/> |
Текущая версия на 17:07, 27 апреля 2008
|
|
|
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
История PostgreSQL Изучаем самый мощный из открытых серверов баз данных
Содержание |
[править] Интерфейсы
ЧАСТЬ 4: Интерфейсы, как известно, бывают не только пользовательскими, но и программными. С первыми мы уже успели познакомиться, а сегодня Евгений Балдин расскажет, какие API существуют для доступа к PostgreSQL из различных языков программирования.
В институте им очень дорожили, так как
попутно он использовался для некоторых
уникальных экспериментов и как переводчик
при общении со Змеем Горынычем.
(О Кощее Бессмертном)
«Понедельник начинается в субботу»
Понятно, что любую базу данных, в принципе, можно заполнить вручную; правда, некоторые придется заполнять очень долго. СУБД – это просто хранилище, а для заполнения и доступа к хранилищу необходима инфраструктура, и эту инфраструктуру надо создавать. Вот такая она – жизнь.
Родной библиотекой для доступа к PostgreSQL является libpq. Написана она на чистом C, что тоже не удивительно, так как это основной язык родной системы. Все остальные языки важны, но безусловно, вторичны.
[править] libpq
Чтобы общаться с базой данных, много функций не требуется: одна для открытия соединения, одна для посылки запроса, одна для получения ответа и одна для закрытия соединения. В реальности, конечно, все немного сложнее, но суть остается неизменной.
[править] К вопросу о переносимости
Библиотека libpq написана на чистом C, поэтому связь с PostgreSQL можно организовать практически везде, где можно найти gcc. Мне как-то пришлось делать это для VAX/VMS – все решилось методом тыка, даже думать почти не потребовалось. Все данные – текст, поэтому вопрос бинарной совместимости платформ попросту отсутствует.
[править] С чего начать
Чтобы воспользоваться вызовами libpq, ее необходимо иметь в системе. В Debian (Sarge) для этого надо установить пакет PostgreSQL-dev:
> sudo apt-get install postgresql-dev
Для доступа к функциям libpq необходимо включить в исходный текст соответствующие заголовки:
#include "libpq-fe.h"
Скрипт pg_config (man pg_config) позволяет получить информацию о том, куда помещаются include-файлы, библиотеки и тому подобное. Для сборки можно также использовать скрипт libpq3-config (man libpq3-config – годится, естественно, только для libpq третьей версии), который заведомо есть в Debian (Sarge):
> #сборка программы > gcc -o "бинарник" "исходник".c -I'pg_config --includedir' \ -lpq '/usr/bin/libpq3-config' > cat /usr/bin/libpq3-config #!/bin/bash echo -lssl -lcrypto -lkrb5 -lcrypt -lresolv -lnsl -lpthread
libpq3-config просто выводит список всех библиотек, от которых зависит libpq.
[править] Открытие и закрытие соединения
Даже открывать соединение с PostgreSQL можно двумя способами:
//открыть соединение PGconn *PQconnectdb(const char *conninfo); //то же, но не блокируя программу PGconn *PQconnectStart(const char *conninfo); //проверка статуса соединения (после PQconnectStart) PostgresPollingStatusType PQconnectPoll(PGconn *conn);
PQconnectdb – обычная функция, принимающая текстовую строку conninfo, содержащую параметры для соединения с сервером, и возвращающая структуру типа PGconn с информацией о созданном соединении и успешности данной операции. В дальнейшем при передаче данных эта структура будет использоваться в качестве параметра.
Передача информации о сервере в качестве строки (conninfo) позволяет не менять внешний интерфейс вызова в случае появления дополнительных параметров и легко добавлять дополнительные опции. Пример открытия соединения:
const char *conninfo= "dbname = test host=localhost"; PGconn *conn=PQconnectdb(conninfo); if (PQstatus(conn) != CONNECTION_OK) { fprintf(stderr, "Не удалось соединиться с базой данных: %s", PQerrorMessage(conn)); /*завершаем работу*/ …}
Параметры передаются в форме «ключевое слово»=«значение». Пары разделяются обычным пробелом. Пробелы вокруг знака равенства можно опустить. Если необходимо передать значение с пробелами, то его необходимо заключить в одинарные кавычки '«составное» «значение»'. Для передачи одинарной кавычки ее необходимо экранировать с помощью обратной косой черты \'. При отсутствии какого-либо параметра в строке conninfo его значение берется из соответствующей переменной окружения, если таковая определена. Если нет, то при открытии соединения используется значение по умолчанию.
Функции открытия соединения распознают следующие параметры и переменные окружения (кое-какие особенности опущены):
- host DNS-имя узла, на котором находится сервер PostgreSQL. Соответствует переменной окружения PGHOST. Значение по умолчанию: localhost.
- hostaddr Числовой адрес узла, на котором находится PostgreSQL (альтернатива host). Соответствует переменной окружения PGHOSTADDR. Значение по умолчанию эквивалентно: localhost.
- port Номер порта, который «слушает» POSTMASTER. Соответствует переменной окружения PGPORT. Значение по умолчанию обычно 5432.
- dbname Имя базы данных. Соответствует переменной окружения PGDATABASE. Значение по умолчанию совпадает с системной учетной записью пользователя.
- user Имя пользователя базы данных. Соответствует переменной окружения PGUSER. Значение по умолчанию совпадает с системной учетной записью пользователя.
- password Поле пароля, если для аутентификации требуется пароль. Соответствует переменной окружения PGPASSWORD. Если аутентификация требуется, а поле не определено, то для доступа используются данные файла ~/.pgpass. Переменная окружения PGPASSFILE может указать другой файл для проведения аутентификации.
- connect_timeout Устанавливает максимальное время ожидания соединения в секундах. С сервером и сетью всякое может случиться. Соответствует переменной окружения PGCONNECT_TIMEOUT. Значение по умолчанию равно 0, что означает бесконечное время ожидания. Не рекомендуется устанавливать значение ожидания меньше 2 секунд.
- options Опции, посылаемые непосредственно серверу, если таковые потребуются. Соответствует переменной окружения PGOPTIONS.
- sslmode Определяет порядок действий при SSL-соединении. Принимает четыре возможных значения:
- disable – без шифрования
- allow – сначала попробовать соединиться без шифрования, а в случае неудачи постараться установить защищенное соединение,
- prefer – сначала попробовать установить защищенное соединение, а в случае неудачи повторить соединение без шифрования,
- require – выполнять только защищенное соединение. Соответствует переменной окружения PGSSLMODE.
Значение по умолчанию: prefer.
- krbsrvname Имя Kerberos-сервиса. Используется для аутентификации с помощью Kerberos-5[1]. Это совершенно отдельная тема, выходящая за рамки данной статьи. Соответствует переменной окружения PGKRBSRVNAME.
- PGDATESTYLE Переменная окружения, позволяющая установить представление времени и даты по умолчанию. Соответствует SQL-команде SET datestyle TO …
- PGTZ Переменная окружения, позволяющая установить текущий часовой пояс. Соответствует SQL-команде SET timezone TO …
- PGCLIENTENCODING Переменная окружения, позволяющая установить кодировку клиента. Соответствует SQL-команде SET client_encoding TO …
Существует целый класс функций, которые позволяют получить информацию о соединении. За подробностями следует обратиться к документации, но для начала полезно знать о двух из них:
ConnStatusType PQstatus(const PGconn *conn); char *PQerrorMessage(const PGconn *conn);
PQstatus возвращает информацию о том, как прошло соединение. Интересны состояния CONNECTION_OK – все хорошо и CONNECTION_BAD – ничего не вышло. Функция PQerrorMessage позволяет получить текстовую строку с описанием последней возникшей проблемы.
Для того, чтобы разорвать соединение, используется функция:
void PQfinish(PGconn *conn);
Внимание! Соединения следует закрывать сразу же, как только в них отпадает необходимость. Число соединений, которые поддерживает POSTMASTER, ограничено – очень легко парализовать работу базы данных, просто открывая новые соединения.
[править] SQL-запросы
Что ж, до сервера мы уже «дозвонились», теперь пора с ним «поговорить».
[править] Выполнение запросов
Простейший способ выполнить SQL-запрос – это воспользоваться функцией PQexec:
PGresult *PQexec(PGconn *conn, const char *command);
В качестве параметров функции передается структура соединения conn и строка с SQL-командой command. Возвращается указатель на структуру типа PGresult, где сохраняется информация, полученная от СУБД в ответ на запрос. При желании можно отсылать сразу несколько SQL-команд в одном запросе, разделяя их ; – точкой с запятой. В этом случае информация, сохраненная в структуре PGresult, будет относиться только к последнему запросу.
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
По умолчанию, каждый PQexec открывает отдельную транзакцию, если явно не начать ее с помощью команды BEGIN. В последнем случае транзакция будет продолжаться либо до COMMIT, либо до ROLLBACK.
Есть более сложный вызов PQexecParams, который позволяет передавать вызов и параметры к этому вызову раздельно. Таким образом исчезает необходимость самостоятельно формировать строку SQL-команды и заботиться об экранировании данных, что важно в случае сохранения бинарных последовательностей. В качестве платы за соображения безопасности PQexecParams способен послать не более одной команды за раз.
В некоторых случаях для увеличения скорости выполнения часто встречающихся запросов полезно обратить внимание на пару функций PQprepare и PQexecPrepared. Эти команды эквивалентны своим SQL-аналогам PREPARE и EXECUTE. Идея оптимизации состоит в том, что прежде чем выполнить запрос, PostgreSQL сначала анализирует его, затем планирует порядок действий и только потом, собственно, выполняет запрос. Первые два этапа для похожих запросов с разными условиями отбора можно выполнить заранее с помощью команды PREPARE. Затем, с помощью команды EXECUTE, можно выполнять подобные уже подготовленные (prepared) запросы.
Все упомянутые выше команды работают с сервером БД синхронным образом, то есть посылают запрос и ждут ответа. Клиентское приложение на это время «засыпает». В libpq предусмотрен целый класс функций, предназначенный для асинхронных операций, не блокирующих клиентское приложение. Их применение усложняет код и логику программы, хотя все в пределах допустимого. С моей точки зрения, лучше организовать все так, чтобы время, использованное на ожидание результатов запроса, не влияло фатально на внешние процессы, и обеспечить бесперебойную работу сети и сервера базы данных.
[править] Информация о состоянии запроса
После выполнения запроса всегда интересно узнать, каково его состояние:
ExecStatusType PQresultStatus(const PGresult *res);
На вход подается структура PGresult, создаваемая в результате работы PQexec-подобных функций, а на выходе получаем информацию о состоянии в виде числа, значение которого можно сравнить со следующими константами:
- PGRES_COMMAND_OK – все прошло хорошо (для запросов, которые не возвращают данные, например, INSERT),
- PGRES_TUPLES_OK – все прошло хорошо, плюс получены данные в ответ на запрос (для запросов типа SELECT или SHOW),
- PGRES_EMPTY_QUERY – строка запроса почему-то была пустой,
- PGRES_COPY_OUT – идет передача данных от сервера,
- PGRES_COPY_IN – идет передача данных на сервер,
- PGRES_BAD_RESPONSE – ошибка, ответ сервера не разборчив,
- PGRES_NONFATAL_ERROR – нефатальная ошибка: предупреждение (notice) или информация к сведению (warning),
- PGRES_FATAL_ERROR – при выполнении запроса произошла серьезная ошибка.
Для получения более подробной информации об ошибке следует воспользоваться функцией
char *PQresultErrorMessage(const PGresult *res);
При вызове этой функции в качестве результата будет сформирована строка с информацией об ошибке или пустая строка, если все прошло хорошо.
[править] Получение данных
При получении данных предполагается, что статус запроса соответствует PGRES_TUPLES_OK. Теперь, если примерно известно, что хочется получить в результате запроса, то для получения данных достаточно четырех функций:
int PQntuples(const PGresult *res); int PQnfields(const PGresult *res); char *PQgetvalue(const PGresult *res, int row_number, int column_number); int PQgetisnull(const PGresult *res, int row_number, int column_number);
Первые две функции являются информационными и позволяют узнать, сколько строк получено в результате запроса (PQntuples) и сколько в каждой такой строке колонок (PQnfields). Возьмите на заметку, что 0 строк – это тоже хороший результат.
Функция PQgetvalue позволяет получить доступ к данным. В качестве параметров кроме структуры соединения (res) передается номер строки (column_number) и номер колонки (column_number). Все данные возвращаются (как и посылаются) в виде текстовой строки, то есть перед употреблением их необходимо перевести в привычный формат. Например, в случае целых чисел можно воспользоваться функцией atoi.
Следует помнить, что данные SQL могут иметь неопределенное значение (NULL). Если подобная возможность существует, то перед получением значения следует проверить, определено ли оно. Pqgetisnull позволяет разобраться с этой проблемой. По передаваемым параметрам эта функция эквивалентна PQgetvalue, а в качестве результата возвращает 1, если значение не определено, и 0, если определено.
Кроме упомянутых выше, существует целый ряд функций, позволяющих получить информацию о данных, как то: имя колонки (PQfname), размер передаваемых данных в байтах (PQgetlength) и тому подобное. Для экранирования специальных символов при операции с бинарными или текстовыми данными есть набор сервисных функций PQescape*.
[править] COPY
SQL-команда COPY является расширением, специфичным для PostgreSQL. Основное преимущество SQL – «все есть понятный текст», в некоторых случаях, когда надо передавать большие объемы данных, оборачивается недостатком. Функции PQputCopyData и PQgetCopyData в ряде случаев позволяют значительно ускорить передачу данных между сервером и клиентом.
[править] Асинхронные сигналы
Стандартный SQL не предполагает взаимодействия разных пользователей, кроме как через изменение данных в таблицах. PostgreSQL позволяет посылать асинхронные сигналы с помощью команд LISTEN и NOTIFY. LISTEN "имя сигнала" передается серверу как обычная SQL- команда. Если статус запроса становится равным PGRES_COMMAND_OK, то это означает, что ранее был выполнен запрос NOTIFY "имя сигнала". Если же инициализация сигнала (NOTIFY) ожидается позже регистрации (LISTEN), то функция PQnotifies позволяет вновь проверить наличие сигнала после любого запроса.
[править] Сборка «мусора»
«Мусор» убирать придется руками. Каждая функция типа PQexec создает объект типа PGresult. После того, как вся необходимая информация о результатах запроса получена, следует освободить память, занимаемую этим объектом с помощью команды:
void PQclear(PGresult *res);
Если утечки памяти вас не волнуют, то можно этого и не делать. В этом случае следует побеспокоиться о том, почему вас не беспокоят утечки памяти?
[править] Большие объекты
Еще один способ сохранять неструктурированные данные в PostgreSQL – это сохранять их в больших объектах (Large Objects). PostgreSQL предоставляет интерфейс, схожий с файловым интерфейсом Unix: open (lo_open), read (lo_read), write (lo_write), lseek (lo_lseek) и так далее. Все lo_* команды работают со значениями, полученными из колонки с типом oid – это специальный тип данных, который является ссылкой на объект произвольного типа. То есть последовательность работы с большим объектом следующая: создается большой объект (lo_create). Далее возвращаемый lo_create указатель oid используется для записи данных в большой объект (lo_import/lo_write), а затем этот указатель вставляется в таблицу с помощью стандартных SQL-операторов. Чтение происходит в обратном порядке (lo_export/lo_read). Все операции с большими объектами должны происходить внутри транзакции.
Следует отметить, что необходимость интерфейса больших объектов на текущий момент не так уж и очевидна. Стандартными средствами в PostgreSQL можно сохранять бинарные данные размером вплоть до 1 Гб, что вполне может соперничать с максимальным размером для большого объекта (2 Гб).
[править] ECPG
Чтобы не отставать от коммерческих баз данных, PostgreSQL имеет свой собственный вариант «встроенного SQL». Эта технология позволяет смешивать обычный язык C с SQL-структурами, примерно следующим образом: // файл test.pgc #include <stdio.h> #include <stdlib.h> // структура для обработки ошибок EXEC SQL include sqlca; // реакция в случае ошибки/предупреждения EXEC SQL whenever sqlwarning sqlprint; EXEC SQL whenever sqlerror do ExitForError(); void ExitForError() { fprintf(stderr,"Все, конец - это фатально.\n"); sqlprint(); exit(1); } int main(int argc, char **argv) { // определение переменных, чтобы их можно было использовать // инструкциях ECPG EXEC SQL BEGIN DECLARE SECTION; const char *dbname = "test"; const char *user = "baldin"; VARCHAR FIO[128]; VARCHAR NUMBER[128]; EXEC SQL END DECLARE SECTION; // соединение с базой данных // внешние переменные предваряются двоеточием EXEC SQL CONNECT TO :dbname USER :user; // определение курсора через SELECT EXEC SQL DECLARE mycursor CURSOR FOR SELECT fio, number FROM fiodata,phonedata WHERE fiodata.id=phonedata.id; EXEC SQL open mycursor; // чтение данных из курсора EXEC SQL FETCH NEXT FROM mycursor INTO :FIO,:NUMBER; while (sqlca.sqlcode == 0) { // не 0, если данные больше нет printf("ФИО: %s номер: %s\n",FIO.arr,NUMBER.arr); EXEC SQL FETCH NEXT FROM mycursor INTO :FIO, :NUMBER; } // разъединение с базой данных EXEC SQL DISCONNECT; } Все SQL-команды начинаются с метки EXEC SQL. Она используется препроцессором ecpg как маркер для конструкций, подлежащих обработке. Внутри SQL-команд можно использовать переменные C. Для этого перед ними необходимо поставить двоеточие «:». Для компиляции выше процитированного файла (test1.pgc) необходимо выполнить следующие действия: > # установить ecpg > sudo apt-get install libecpg-dev > # запустить препроцессор > ecpg test1.pgc > # скомпилировать получившийся файл > gcc -o test1 test1.c -I`pg_config --includedir` -lecpg > # проверить работоспособность программы > ./test1 ФИО: Иванов И.П. номер: 555-32-23 ФИО: Балдин Е.М. номер: 555-41-37 ФИО: Балдин Е.М. номер: (+7)5559323919 Удобно это или нет – решайте сами. |
|
[править] Все остальное
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
Эта статья называется «Интерфейсы», но большая часть ее посвящена только одному из них. Дело в том, что этот один является родным и наиболее полным, а все остальное – лишь подмножество. В простейшем случае все интерфейсы одинаковы: открыл соединение, послал запрос, обработал результаты, закрыл соединение. Также заметна энергосберегающая тенденция везде делать ровно один интерфейс на все типы СУБД.
[править] bash
Да, да к bash тоже есть свой интерфейс, правда для этого надо наложить специальный патч. Возни, конечно, немало – зато к базе данных можно будет обращаться прямо из shell-скриптов.
Сайт проекта: http://www.psn.co.jp/postgresql/pgbash/index-e.html.
[править] Java
Совершенно ожидаемо, что Java общается с PostgreSQL стандартным образом, а именно через JDBC. Поэтому, если вы знакомы с Java [а если нет – зачем вам использовать ее для доступа к PostgreSQL? – прим. ред.], то достаточно добыть драйвер JDBC для PostgreSQL, например отсюда: http://jdbc.postgresql.org/. В Debian (Sarge) достаточно набрать
> sudo apt-get install libpgjava
и, прочитав README к пакету, приступить к работе.
[править] Lisp
Точнее, Common Lisp. Скорее всего, эти драйвера подойдут и для других диалектов:
> sudo apt-get install cl-pg #или > sudo apt-get install cl-sql-postgresql
Второй вариант является драйвером для единого интерфейса доступа к SQL-базам данных из Common Lisp CLSQL (http://clsql.b9.com/).
[править] Perl
Интерфейс для связи с PostgreSQL DBD-Pg используется в Perl через DBI[2]. Все подробности доступны на CPAN: http://search.cpan.org/~dbdpg/dbd-pg/pg.pm.
> sudo apt-get install libdbd-pg-perl
DBD-Pg охватывает, фактически, все имеющиеся на сегодня возможности PostgreSQL: от больших объектов (large objects) до точек сохранения (savepoints).
[править] PHP
О том как использовать PostgreSQL в PHP-проектах можно прочитать здесь: http://www.php.net/manual/en/ref.pgsql.php. Драйвер, скорее всего, тоже доступен в репозиториях дистрибутива:
> sudo apt-get install php4-pgsql
Говорят, почти единственной причиной, по которой PHP-разработчики предпочитают MySQL, является то, что раньше не было «родной» версии PostgreSQL под Windows. Начиная с PostgreSQL 8.0, конкретно этот довод «против» уже не работает.
[править] Python
Модуль для Python существует уже больше десяти лет. Подробности можно узнать здесь: http://www.druid.net/pygresql/. Установка модуля:
> sudo apt-get install python-pygresql
[править] Ruby
Кое-что можно прочесть здесь: http://ruby.scripting.ca/postgres/. Установка происходит как обычно:
> sudo apt-get install libdbd-pg-ruby
[править] ODBC
Разработка драйвера идет на pgFoundry. Аскетичная страничка проекта доступна по адресу: http://pgfoundry.org/projects/psqlodbc/. Установка:
> sudo apt-get install odbc-postgresql
[править] Послесловие
Конечно, наш обзор интерфейсов к PostgreSQL нельзя назвать всеобъемлющим, но изложенных сведений вполне хватит для того, чтобы начать работать. Если впоследствии вам придет в голову идея «дописать что-то свое», не спешите хвататься за перо, то есть клавиатуру – советую сначала обратиться по адресу http://techdocs.postgresql.org/oresources.php и посмотреть, что уже сделано.
- ↑ Kerberos — промышленный стандарт для аутентификации и взаимодействия в условиях незащищенного окружения. Алгоритмы Kerberos основаны на шифровании с использованием симметричного криптографического ключа и требуют наличия доверенного агента.
- ↑ DBI — унифицированный интерфейс для доступа к данным. Подробнее об этом пакете можно узнать на CPAN: http://search.cpan.org/~timb/DBI-1.52/DBI.pm