Шрифт:
Интервал:
Закладка:
DECLARE VARIABLE COMMENTS CHAR(20) = '/* */';
BEGIN
/* Необходимо для некоторых редакторов пользовательского интерфейса */
IF (ROLENAME = '') THEN ROLENAME = NULL;
IF (USR = '') THEN USR = NULL;
IF (PRIV = '') THEN PRIV = NULL;
/* Недостаточно данных для выполнения работы */
IF ( (PRIV IS NULL AND ROLENAME IS NULL) OR USR IS NULL) THEN EXIT;
/* Если это имя роли, мы будем с ней работать */
IF (ROLENAME IS NOT NULL) THEN
BEGIN
/* Если задано имя роли, то создается роль, если она требуется */
IF (CREATE_ROLE = 1) THEN BEGIN
PERM = 'CREATE ROLE ' || ROLENAME || ' ; ' ;
SUSPEND;
PERM = 'COMMIT; ' ;
SUSPEND;
PERM = COMMENTS;
SUSPEND;
END
VUSR = ROLENAME;
END
/* Если существует имя роли, мы применим полномочия к этой роли и предоставим эту роль указанному пользователю */
ELSE
/* Нас не интересует роль: полномочия только для пользователя */
VUSR = USR;
/* Выяснение - этот скрипт GRANT или REVOKE */
IF (CMD STARTING WITH 'G') THEN
STUB = 'GRANT';
ELSE
STUB = 'REVOKE ';
IF (ROLENAME IS NOT NULL) THEN
BEGIN
IF (STUB = 'GRANT') THEN
BEGIN
/* Предоставление роли пользователю */
STRING = STUB || ROLENAME || ' TO ' || USR;
IF (GRANTOPT = 1) THEN
STRING = STRING || ' WITH ADMIN OPTION ;';
ELSE
STRING = STUB || ROLENAME || ' FROM ' || DSR || PERM = STRING;
SUSPEND;
PERM = COMMENTS;
SUSPEND;
END
/* Если передано ANY в качестве привилегии, создаем отдельно каждую привилегию */
IF (PRIV = 'ANY') THEN
STUB = STUB || 'SELECT, DELETE, INSERT, UPDATE, REFERENCES ON ';
ELSE
STUB = STUB || PRIV || ' ON ' ;
/* Просмотр всех имен таблиц и просмотров и создание для каждого оператора */
FOR SELECT RDB$RELATION_NAME FROM RDB$RELATIONS
WHERE RDB$RELATION_NAME NOT STARTING WITH 'RDB$'
INTO : RELNAME DO
BEGIN
STRING = STUB || :RELNAME || ' '
IF (CMD STARTING WITH 'G') THEN
STRING = STRING || 'TO ';
ELSE
STRING = STRING || 'FROM ';
STRING = STRING || VUSR;
IF (CMD STARTING WITH 'G'
AND GRANTOPT = 1 AND ROLENAME IS NULL) THEN
STRING = STRING || ' WITH GRANT OPTION ;';
ELSE
STRING = STRING || ' ;';
PERM = STRING;
SUSPEND;
END
PERM = COMMENTS;
SUSPEND;
END ^
SET TERM ;^
Создание и выполнение скриптаПерейдите в каталог Firebird /bin и запустите isql, соединитесь с базой данных как пользователь SYSDBA. Вы используете процедуру для создания скрипта, который добавит роль 'MANDRAKE', предоставит эту роль пользователю USER1, а потом установит полномочия для этой роли. Затем снова сделает то же самое с существующей ролью 'PURPLE' для пользователя USER2:
SQL> OUTPUT L:DATAEXAMPLESPERMSCRIPT.SQL;
SQL> SELECT * FROM PERMSCRIPT ('G', 'ALL', 'USER1', 'MANDRAKE', 1, 1);
SQL> COMMIT;
SQL> SELECT * FROM PERMSCRIPT ('G', 'ALL', 'USER2', 'PURPLE', 1, 0);
SQL> COMMIT; SQL> OUTPUT;
SQL> INPUT L:DATAEXAMPLESPERMSCRIPT.SQL;
SQL> COMMIT; SQL> SHOW GRANT;
Вот и все. Вы получите сообщение об ошибке, когда утилита INPUT встретит текст не SQL, напечатанный в OUTPUT, однако это не повлияет на вывод полномочий.
Инсталляция полномочий непосредственно из процедуры
Процедура GRANT_PERMS, показанная в листинге 35.2, в основном похожа на процедуру PERMSCRIPT из листинга 35.1. Вместо того чтобы создавать набор выходных строк для выполнения под isql в качестве скрипта, она непосредственно устанавливает полномочия через EXECUTE STATEMENT. Такая техника недоступна в Firebird 1,0.x.
Листинг 35.2. Процедура полномочий
/* (с) Helen Borrie 2004, free for use and modification under the Initial Developer's Public License */
SET TERM ^;
CREATE PROCEDURE GRANT_PERMS
(CMD VARCHAR(6) ,
PRIV CHAR(10),
USR VARCHAR (31) ,
ROLENAME VARCHAR(31),
GRANTOPT SMALLINT)
AS
DECLARE VARIABLE RELNAME VARCHAR (31);
DECLARE VARIABLE EXESTRING VARCHAR(1024) = '';
DECLARE VARIABLE EXESTUB VARCHAR (1024 ) = '';
BEGIN
IF (ROLENAME = ' ' ) THEN ROLENAME = NULL;
IF (USR = '') THEN USR = NULL;
IF (PRIV = '') THEN PRIV = NULL;
IF ((PRIV IS NULL AND ROLENAME IS NULL) OR USR IS NULL) THEN EXIT;
IF (CMD STARTING WITH 'G') THEN
EXESTUB = 'GRANT ';
ELSE
EXESTUB = 'REVOKE ';
IF (ROLENAME IS NOT NULL) THEN
BEGIN
IF (EXESTUB = 'GRANT') THEN
BEGIN
EXESTUB = EXESTUB || ROLENAME || ' TO ' || USR;
IF (GRANTOPT = 1) THEN
EXESTUB = EXESTUB || ' WITH ADMIN OPTION';
ELSE
EXESTUB = EXESTUB || ROLENAME || ' FROM ' || USR;
EXECUTE STATEMENT EXESTUB;
END
ELSE
BEGIN
IF (PRIV = 'ANY') THEN
EXESTUB = EXESTUB || 'SELECT,DELETE,INSERT,UPDATE,REFERENCES ON ';
ELSE
EXESTUB = EXESTUB || PRIV || ' ON ' ;
FOR SELECT RDB$RELATION_NAME FROM RDB$RELATIONS
WHERE RDB$RELATION_NAME NOT STARTING WITH 'RDB$'
INTO : RELNAME DO
BEGIN
EXESTRING = EXESTUB || :RELNAME || ' ';
IF (CMD STARTING WITH 'G') THEN
EXESTRING = EXESTRING || 'TO ';
ELSE
EXESTRING = EXESTRING || 'FROM ';
EXESTRING = EXESTRING || USR;
IF (GRANTOPT = 1) THEN
EXESTRING = EXESTRING || ' WITH GRANT OPTION';
EXECUTE STATEMENT EXESTRING;
END
END
END ^
SET TERM ;^
Если вы сами хотите поэкспериментировать с этими скриптами и изменить их для ваших потребностей, вы можете найти исходные тексты в разделе Download на http://www.apress.com, в файле permscripts.sql.
Пора дальшеСледующая (и последняя) глава этой части содержит множество тем, связанных с архитектурными вариантами сервера, включая раздел по инсталляции и использованию встроенного Суперсервера под Windows. Установки файла конфигурации в firebird.conf или isc config/ibconfig могут быть найдены в этой главе вместе с темой безопасности параметров конфигурации, связанных с использованием в Firebird внешних выполняемых и других файлов.
ГЛАВА 36. Конфигурация и специальные возможности.
Эта глава представляет собой попурри на темы, которые будут интересны тем разработчикам, кто хорошо знаком с практическими вопросами выполнения Firebird.
Сначала описываются архитектурные отличия между моделями Firebird Классический сервер и Суперсервер. Затем обсуждаются различные параметры конфигурации сервера и некоторые руководящие принципы разработки для встроенного сервера под Windows.
В заключение мы рассмотрим коды пользовательских внешних модулей, которые вы можете писать для использования на серверной стороне, чтобы выполнять специальные вычисления и преобразования (внешние функции), конвертирование BLOB из одного формата в другой (фильтры BLOB) и реализовывать международные наборы символов. В конце этой темы содержатся подробности по конфигурированию доступа к файловой системе сервера для этих и других внешних объектов.
Сравнение архитектуры Суперсервера и Классического сервера
Хотя Суперсервер и Классический сервер имеют много общих характеристик - действительно, они созданы из одного базового кода, - они представляют совершенно различные модели внутренних операций.
Выполняемые программы и процессы
Классический сервер выполняется как один серверный процесс на каждое соединение (рис. 36.1). Когда клиент пытается соединиться с базой данных Firebird, экземпляр исполняемого модуля fb inet_server инициализируется и продолжает оставаться предназначенным для этого клиентского соединения в течение всего времени этого соединения. Когда клиент отсоединяется от базы данных, экземпляр серверного процесса завершается.
Суперсервер выполняется как один вызов выполняемого модуля fbserver (рис. 36.2). fbserver запускается один раз системным загрузочным скриптом или системным администратором и остается запущенным, ожидая запросов на соединение. Процесс завершается явным остановом.
Рис. 36.1. Сеть Классического сервера и модель процесса
Управление блокировками
При Классическом сервере каждый клиентский процесс сервера имеет свой собственный, связанный с базой данных кэш, и множество процессов борются за доступ к базе данных. Подсистема управления блокировками, fb lockrngr, использует методы внутреннего процесса связи (Inner-Process Communication, IPC) для управления и синхронизации доступа параллельных процессов к страницам.
В Суперсервере менеджер блокировок реализован как поток процесса fbserver и использует механизмы внутрипоточной связи вместо механизма сигнализации POSIX.
Подробности внутреннего управления блокировками см. в главе 40.
Использование ресурсов
В Классическом сервере каждый экземпляр fb_inet_server выделяет в своей области памяти статический кэш для страниц базы данных. Поэтому использование ресурсов линейно возрастает с каждым дополнительным клиентским соединением. Однако, когда количество одновременных соединений относительно мало, Классический сервер использует меньше ресурсов.
Рис. 36.2. Сеть Суперсервера и модель процесса
Суперсервер использует единое пространство кэша, которое совместно используется клиентскими подключениями, что позволяет более эффективно использовать и управлять памятью кэша при большом увеличении количества одновременных соединений.
Локальный доступ
Классический сервер позволяет процессам приложений, которые выполняются на той же машине, где находятся сервер и базы данных, выполнять прямые операции ввода/вывода с базой данных.
За исключением встроенного сервера Суперсервер требует, чтобы приложения использовали сетевые методы для запросов ввода/вывода, и удовлетворяет эти запросы по сети. В Linux Суперсервер не поддерживает локальный прямой доступ.
* На платформах, отличающихся от Windows (и также рекомендовано для Windows), локальные соединения с Суперсервером через сервер localhost (с адресом IP по соглашению 127.0.0.1).
* Сервер Windows и локальный клиент могут имитировать сетевое соединение через совместно используемое пространство IPC. Этот механизм, называемый локальным доступом, не может безопасно обрабатывать множество соединений. После Firebird 1.5 он замещается локальным методом доступа с использованием подсистемы XNET.
- Delphi. Учимся на примерах - Сергей Парижский - Программирование
- Сделай видеоигру один и не свихнись - Слава Грис - Программирование / Руководства
- Психбольница в руках пациентов - Алан Купер - Программирование