Шрифт:
IF (GRANT_OPTION = 1) THEN
W_GRANT_OPTION = 'Y';
ELSE
W_GRANT_OPTION = '';
Теперь другой запрос к RDB$ROLES, на этот раз для поиска объекта, к которому применяется привилегия роли. Если такой найден, мы добавляем к имени этого объекта полезный префикс. Если это не роль, мы проверяем, является ли наш объект столбцом таблицы, и присваиваем его имени квалификатор.
IS_ROLE = NULL;
SELECT 1 FROM RDB$ROLES
WHERE RDB$ROLE_NAME = :RELATION_NAME
INTO :IS_ROLE;
IF (IS_ROLE = 1) THEN
QUALIFIED_OBJECT = '(Role) ' ||RELATION_NAME;
ELSE
BEGIN
IF (
(FIELD_NAME IS NULL)
OR (RTRIM(FIELD_NAME) = '')) THEN
FIELD_NAME = ' ';
ELSE
FIELD_NAME = '.'|| FIELD_NAME;
QUALIFIED_OBJECT = RELATION_NAME || FIELD_NAME;
END
В RBD$USER_PRIVILEGES и таблицы, и просмотры имеют тип объекта 0. Это не слишком хорошо для нас, значит, следующий запрос проверяет по таблице RDB$RELATIONS, является ли этот конкретный объект просмотром:
IF (OBJECT_TYPE = 0) THEN
BEGIN
IS_VIEW = 0;
SELECT 1 FROM RDB$RELATIONS
WHERE RDB$RELAT | ON_NAME = : RELATION_NAME
AND RDB$VIEW_SOURCE IS NOT NULL
INTO :IS_VIEW;
IF (IS_VIEW = 1) THEN
OBJECT_TYPE = 1;
END
В этой точке нашего цикла мы получили почти все, что хотели. Однако наш объект все еще имеет свой внутренний номер, и мы все еще не знаем тип "пользователя". Пользователями могут быть не только люди. Именно здесь мы выполняем вложенные вызовы для выполнения трансляции внутренних номеров в осмысленные строки. Когда мы это сделаем, наша запись готова к выводу в кэш строк, и мы вызываем SUSPEND для завершения цикла.
Вызовы вложенных процедур из триггеров или хранимых процедур почти идентичны вызовам, которые мы используем в DSQL. Синтаксис отличается только там, где мы обрабатываем возвращаемые значения. В DSQL сервер передает возвращаемые значения клиенту в виде структуры записи. В хранимых процедурах мы используем ключевое слово PSQL RETURNING_VALUES и предоставляем переменные для получения этих значений.
EXECUTE PROCEDURE SP_GET_TYPE(:OBJECT_TYPE)
RETURNING_VALUES (:Q_OBJECT_TYPE);
EXECUTE PROCEDURE SP_GET_TYPE (:USER_TYPE)
RETURNING_VALUES (:Q_USER_TYPE);
SUSPEND;
END
END^
Вот еще один простой вызов:
SELECT * FROM SP PRIVILEGES;
Если нам не нужны все столбцы или хотим получить их в особом порядке, мы можем сделать это. Предположим, мы просто хотим посмотреть привилегии всех пользователей-людей, отличных от SYSDBA:
SELECT
USER_NAME,
QUALIFIED_OBJECT,
PRIVILEGE
FROM SP_PRIVILEGES
WHERE Q_USER_TYPE = 'User'
AND USER_NAME <> 'SYSDBA'
ORDER BY USER_NAME, QUALIFIED_OBJECT;
Могут быть использованы заменяемые параметры поиска:
SELECT
USER_NAME,
QUALIFIED_OBJECT,
PRIVILEGE
FROM SP_PR1VILEGES
WHERE Q_USER_TYPE = ?
ORDER BY USER_NAME, QUALIFIED_OBJECT;
! ! !
СОВЕТ. Вы можете найти эту процедуру полезной для проверки привилегий SQL в вашей базе данных. Информацию об установке привилегий см. в главе 35.
. ! .
Процедура с промежуточными итогами
В этой процедуре мы обрабатываем записи таблицы SALES базы данных EMPLOYEE. Мы получим два итога: один для каждого вида продаж, а другой - для всех продаж. В качестве входа мы просто используем начальную и конечную даты для группы интересующих нас продаж.
SET TERM ^;
CREATE PROCEDURE LOG_SALES (
.START_DATE DATE,
END_DATE DATE)
RETURNS (REP_NAME VARCHAR (37) ,
CUST VARCHAR(25),
ORDDATE TIMESTAMP,
ITEMTYP VARCHAR(12),
ORDTOTAL NUMERIC(9,2),
REPTOTAL NUMERIC(9,2),
RUNNINGTOTAL NUMERIC(9, 2))
AS
DECLARE VARIABLE CUSTNO INTEGER;
DECLARE VARIABLE REP SMALLINT;
DECLARE VARIABLE LASTREP SMALLINT DEFAULT -99;
DECLARE VARIABLE LASTCUSTNO INTEGER DEFAULT -99;