Check-in и check-out малой кровью

Известно — там, где не предусмотрены стандартные средства чего-либо, обязательно (обязательно) найдется свой Левша, который с помощью молотка, веревки и смекалки (!) сделает так, как никому и не снилось.

Сегодня в студии разбирается вопрос организации работы роты программистов над отдельно взятым проектом. Боевая задача — запретить одновременное редактирование одного и того же объекта разными людьми.

На помощь приходят все те же триггеры на таблицу Объект (SQL триггеры, естественно). Дополнительно потребуется таблица [Object Locking], в которую пишется лог check-in’ов и check-out’ов. Архив, содержащий скрипт и таблицу:

  nav-checkout (1,6 KiB, 1 825 hits)

Теперь, чтобы получить возможность делать изменения (а точнее, сохранять их, но к этому все быстро привыкают), надо записать свой логин в строку с версией объекта.
Убрать логин из версии — означает, снять блокировку.
Никто другой убрать логин не может — только сам поставивший.
Если у поставившего случился понос или золотуха, а снять надо, то решение очевидно — временно отключить сам триггер.

P.S. Подразумевается, что в команде работают адекватные люди, понимающие выгоды от хорошей постановки процесса :) Остальных — выжигать каленым железом, либо перевоспитывать (вести себя по-отечески, т.е. объяснять, наказывать и прочая). Это уж кому как нравится.

--Запрет на модификацию объекта без предварителього checkout'a, запрет на checkout,
-- если объект взят другим пользователем, вставка в лог
CREATE TRIGGER dbo.Trg_Cath_CheckInOut ON dbo.Object
FOR UPDATE
   
AS

BEGIN
    SET NOCOUNT ON
    DECLARE @old_blocked_by_user VARCHAR(20), @new_blocked_by_user VARCHAR(20)
    DECLARE @old_size INT, @new_size INT
    DECLARE @old_version VARCHAR(250), DECLARE @new_version VARCHAR(250)
   
    SELECT @old_size=[BLOB SIZE], @old_version=[Version List]
    FROM deleted
   
    SELECT @new_size=[BLOB SIZE], @new_version=[Version List]
    FROM inserted
   
    SELECT @old_blocked_by_user =u.[USER ID]
    FROM deleted d
        INNER JOIN dbo.[USER] u
        ON CHARINDEX(u.[USER ID], d.[Version List])<>0-- and u.[User ID]<>SUSER_NAME()
   
    SELECT @new_blocked_by_user =u.[USER ID]
    FROM inserted i
        INNER JOIN dbo.[USER] u
        ON CHARINDEX(u.[USER ID], i.[Version List])<>0  

    --проверяем логин на старой версии записи
    IF ISNULL(@old_blocked_by_user, '')<>SUSER_NAME() AND @old_blocked_by_user<>'' AND ISNULL(@old_size, -1)>=0 BEGIN
        RAISERROR ('Объект занят пользователем %s', 16, 1,  @old_blocked_by_user)
        ROLLBACK TRANSACTION
        RETURN
    END
   
    --если модификация
    --проверяем логин на новой версии записи, при условии что изменился код объекта
    --и вставляем записи в лог при условии что сменился user
    IF ISNULL(@old_size, -1)>=0 AND ISNULL(@new_size, -1)>=0 BEGIN
        IF @old_size<>@new_size AND ISNULL(@new_blocked_by_user, '')<>SUSER_NAME() BEGIN
            RAISERROR('Для модификации объекта необходимо ввести логин и задачу в списке версий', 16, 1)
            ROLLBACK TRANSACTION
            RETURN
        END
       
        IF ISNULL(@new_blocked_by_user, '')=SUSER_NAME() AND
            ISNULL(@old_blocked_by_user, '')<>SUSER_NAME()  BEGIN
            --check out
            INSERT INTO dbo.[Object Locking]
            ([Object TYPE], [Object ID], [Object Version], [Checkout DT], [Checkin DT], [USER ID])
            SELECT TYPE, ID, [Version List], GETDATE(), '17530101', SUSER_NAME()
            FROM inserted
            IF @@error<>0 BEGIN
                RAISERROR('Ошибка при вставке в таблицу Object Locking', 16, 1)
                ROLLBACK TRANSACTION
                RETURN
            END
        END
       
        IF ISNULL(@old_blocked_by_user, '')=SUSER_NAME() AND
            ISNULL(@new_blocked_by_user, '')<>SUSER_NAME()  BEGIN
            --check in
            UPDATE l
            SET [Checkin DT]=GETDATE()
            FROM [Object Locking] l
                INNER JOIN inserted i
                ON i.ID=l.[Object ID] AND i.TYPE=l.[Object TYPE]
            AND YEAR([Checkin DT])=1753
            IF @@error<>0 BEGIN
                RAISERROR ('Ошибка при обновлении данных в таблице Object Locking', 16, 1)
                ROLLBACK TRANSACTION
                RETURN
            END

        END

    END
END

Автор:

Количество статей, опубликованных автором: 4. Дополнительная информация об авторе появится вскоре.

Добавить комментарий

Дополнительные статьи из рубрики "Microtools"