13 авг. 2011 г.

Применение SELECT FROM SELECT

Конструкция SELECT FROM SELECT замечательная вещь. Вот здесь приведено решение задачи поиска строк, содержащих все заданные слова в любой последовательности.

5 авг. 2011 г.

Логирование и отображение исключений

Начиная с версии 2.5.12 необработанные исключения отображаются вместе с наименованием модуля, номером строки исходного кода и стеком вызова:


Для этого в gedemin.exe должна быть залинкована отладочная информация. Ежедневно собираются и выкладываются на сайт два архива -- Гедымин с отладочной информацией и без.

Вместе с выводом на экран информация об исключениях заносится в таблицу GD_JOURNAL и может быть просмотрена в окне Просмотр событий (раздел Исследователь - Сервис - Администратор). Отфильтровать нужные записи можно по полю source, которое будет содержать слова Exception или Macros Exception.

Код Exceptional Magic, отвечающий за обработку исключений, включается в проект через символ условной компиляции EXCMAGIC_GEDEMIN. К сожалению, данный продукт не является open source. Поэтому вы не найдете его в публичных исходниках Гедымина. При необходимости, Вы можете самостоятельно купить исходный код Exceptional Magic. Выложить файлы в папку Gedemin\Log, определить вышеуказанный символ и перекомпилировать весь проект.

2 авг. 2011 г.

Обновление сервера Firebird 2.5 из снэпшота

Внимание! Нижесказанное относится к ситуации, когда сервер Fierbird 2.5.x обновляется новейшей сборкой 2.5.x. Если вы до сих пор работаете на Yaffil, Firebird 1.x, 2.0.x или 2.1.x, то сначала необходимо осуществить процедуру перехода на 2.5.

На сайте firebirdsql.org регулярно обновляются текущие "snapshot" сборки сервера, включающие все последние изменения. Файлы Windows версии 2.5.х можно скачать отсюда. Архивы доступны в формате Zip и 7-Zip, для 32-х и 64-х битных версий ОС. Буквы PDB в имени архива означают, что он содержит сервер, откомпилированный с отладочной информацией.

Обновить работающий сервер на предприятии можно следующим образом:

  1. Делаем архивную копию базы данных и сохраняем ее в надежном месте.
  2. Скачиваем архив с текущей сборкой.
  3. Все пользователи закрывают у себя Гедымин. Если Гедымин работает, а соответствующий пользователь недоступен (вышел покурить, отошел на обед и т.п.), то:
    1. в окне Подключенные пользователи последовательно отключаем активные коннекты или в SQL редакторе выполняем команду DELETE FROM mon$attachments.
    2. если не помогло: на сервере отключаем сетевое соединение или просто выдергиваем кабель локальной сети (не 220В!) из компьютера. Ждем 4-5 минут, пока не отвалятся все коннекты. Если используется версия сервера классической архитектуры, то смотрим в Диспетчер задач, пока там не останется только один процесс fb_inet_server.

    Первый вариант предпочтительнее, но практика показывает, что на крупном предприятии трудно оповестить всех пользователей о том, что не следует загружать Гедымин. В результате, после обрыва соединения пользователь пытается запустить программу снова и снова. В таком случае, второй вариант, с выдергиванием сетевого кабеля, остается единственным решением.

  4. Убедившись, что все пользователи отключены, заходим в Управление компьютером, Службы и останавливаем Firebird.

    Ни в коем случае нельзя снимать задачу fb_inet_server или fbserver через Диспетчер задач. Такое действие может привести к повреждению файла базы данных (особенно, если отключен режим принудительной записи). Если все же в процессе работы сервера пришлось произвести принудительную перезагрузку, выключение или остановку задачи, то после восстановления работоспособности, первым делом следует проверить файл базы данных командой gfix.

  5. Заменяем файлы в папке C:\Program Files\Firebird содержимым архива. Кроме файла security2.fdb! Его не трогаем.

    Если вы случайно затерли security2.fdb, то придется подключиться Гедымином под учетной записью Administrator и в разделе Исследователь-Сервис-Администратор-Пользователи, на панели инструментов выбрать команду Пересоздать всех пользователей.

  6. Cкачиваем отсюда актуальную библиотеку GUDF.DLL (в соответствии с разрядностью вашей операционной системы) и заменяем ею существующий файл в подкаталоге UDF.
  7. Запускаем службу.
  8. Восстанавливаем сетевое соединение.
Посмотреть версию сервера можно в Гедымине: в главном меню выбрать команду О программе....

После обновления сервера рекомендуется провести бэкап-рестор базы данных и обновить клиентскую библиотеку -- файл fbclient.dll.

28 июл. 2011 г.

Firebird на Rosetta Code

Rosetta Code -- сайт, где собраны решения сотен задач на разных языках программирования.

Добавил первые программки для Firebird.

25 июл. 2011 г.

Репликация средствами Firebird

Одна треть от обновленного механизма закрытия периода -- репликация изменений с оперативной на архивную базу данных. Теперь возьмемся за задачу быстрого начального формирования оперативной базы данных.

Рисунки подготовлены в он-лайн сервисе gliffy.com.

19 июл. 2011 г.

Delphi XE 2 (Pulsar) 64 bit

Стали участниками бета тестирования новейшей разработки Embarcadero. С минимальными изменениями удалось перекомпилировать GUDF.DLL под 64 бита. Работоспособность библиотеки еще не проверяли. Будущая Делфи обещает много вкусного, но рассказывать пока нельзя. Подписка о неразглашении.

15 июл. 2011 г.

Охота за исключениями

Ради покупки Exceptional Magic пришлось открыть долларовую Visa, так как Технобанк запретил валютные платежи с рублевых карточек.

Сделаем отдельный Гедымин с отладочной информацией и логированием всех неотловленных исключений в табличку GD_JOURNAL вместе с полным стеком вызова. Должно помочь в отлове фантомных AV и прочих неприятностей.

Почему Exceptional Magic? Приемлемая цена (50 USD с исходниками) и хорошие отзывы на StackOverflow.

26 июн. 2011 г.

Структура презентации проекта

  1. Общая информация о предприятии. Название. Сфера деятельности. Базовые показатели: численность персонала, объемы выпуска, количество единиц машино-тракторного парка и т.п. Где находится. Как добраться. (Только для первой презентации).
  2. Уровень автоматизации предприятия. История взаимоотношений (для наших клиентов). Установленное ПО. Ответственные лица. Базовые параметры: количество компьютеров, наличие сети, конфигурация сервера и т.п.
  3. Действующее соглашение с клиентом. Условия подписанного договора. Сроки.
  4. Информация об автоматизируемом участке. Описание технологического процесса. Участники технологического процесса.
  5. Текущая организация документоооборота и информационных потоков на автоматизируемом участке. Участники, с подробным описанием роли и выполняемых операций каждого.
  6. Реализуемая организация документооборота и информационных потоков. Участники, с подробным описанием роли и выполняемых операций каждого. Подробное, пошаговое описание действий при ежедневной эксплуатации, закрытии периода и построении отчетных форм.
  7. Информация по проекту. Какие базовые настройки будут использованы. Какие настройки будут разработаны специально для клиента. Структуры данных. Документы. Алгоритмы. Типовые хозяйственные операции. Корреспонденция счетов. Взаимодействие и обмен данными со сторонним ПО. Сопряжение с действующими модулями в рамках платформы Гедымин. Подключение внешнего оборудования.
  8. Выходные формы. Образей для каждой. Информация на основании чего строится форма, как вычисляется/заполняется каждое поле.
  9. Таймлайн. Порядок выполнения работ. Сроки. Ответственные.

25 июн. 2011 г.

Быстродействие триггера на коммит транзакции

Насколько замедлит выполнение кода наличие триггера на коммит транзакции?

Тестовый пример 10 000 раз извлекает имя контакта с идентификатором 650 001.
EXECUTE BLOCK
AS
  DECLARE VARIABLE I INTEGER = 0;
  DECLARE VARIABLE S VARCHAR(60);
BEGIN
  WHILE (:I < 10000) DO
  BEGIN
    EXECUTE STATEMENT
      'SELECT name FROM gd_contact WHERE id=650001'
    WITH COMMON TRANSACTION
    INTO :S;
    I = :I + 1;
  END
END
На общей транзакции время выполнения у нас составило 367 мс. Теперь повторим тоже самое, но каждый селект будет выполняться на своей, автономной транзакции:
EXECUTE BLOCK
AS
  DECLARE VARIABLE I INTEGER = 0;
  DECLARE VARIABLE S VARCHAR(60);
BEGIN
  WHILE (:I < 10000) DO
  BEGIN
    EXECUTE STATEMENT
      'SELECT name FROM gd_contact WHERE id=650001'
    WITH AUTONOMOUS TRANSACTION
    INTO :S;
    I = :I + 1;
  END
END
Время выполнения составило 13 000 мс. Как видно, 10 000 стартов и коммитов транзакции не даются нам даром. Создадим пустой триггер на коммит транзакции:
CREATE OR ALTER TRIGGER tc_test
  ACTIVE
  ON TRANSACTION COMMIT
  POSITION 9000
AS
BEGIN
END
Время выполнения с таким триггером также составляет 13 000 мс. Для сравнения добавим в триггер операторы:
CREATE OR ALTER TRIGGER tc_test
  ACTIVE
  ON TRANSACTION COMMIT
  POSITION 9000
AS
  DECLARE VARIABLE S VARCHAR(255);
BEGIN
  S = RDB$GET_CONTEXT('USER_TRANSACTION', 'TEST');
  IF (:S IS NULL) THEN
  BEGIN
    S = 'A';
  END
END
Время выполнения увеличилось на 700 мс (по 0.7 мс в расчете на одну итерацию).

Вывод: Для Firebird 2.5 само по себе наличие триггера на коммит транзакции не увеличивает время выполнения кода.

5 мая 2011 г.

Value exceeds the range for valid dates

Придешь на работу с наилучшими намерениями, а в результате битый день носишся вокруг костра и стучишь в бубен. Получили мы доисторическую клиентскую базу Гедымина, еще на Yaffil-e. Внешне она не выглядела поврежденной: gfix не сообщал об ошибках, и архивирование-восстановление проходило без проблем. Но, в процессе апгрейда под Firebird 2.5, конвертер слетал напрочь.

Каких только действий не предпринималось. Перекомпилировали процедуры и триггеры, перерегистрировали внешние функции, перепробовали разные сборки серверов, удаляли подозрительные метаданные — все безрезультатно. Когда попробовали вручную перевести базу под Firebird 2.0, в процессе восстановления из архива наконец-то появилось более-менее осмысленное сообщение: "value exceeds the range for valid dates gds_$receive failed". Каким-то образом, поле типа дата содержало значение, которое Yaffil считал допустимым, а Firebird категорически отказывался принимать.

Предпринятая сходу попытка переприсвоить все поля типа дата запросами вида:
update gd_document set documentdate = documentdate
привела к уходу сервера "в себя". Стало ясно, что сначала надо определить проблемную таблицу, затем найти в ней нужные строки и работать с ними. С помощью запроса ниже был сформирован скрипт:
select
  'select max( ' || r.rdb$field_name || 
  ') from ' || r.rdb$relation_name || ';'
from
  rdb$relation_fields r
    join rdb$fields f on 
      f.rdb$field_name = r.rdb$field_source
where
  f.rdb$field_type = 13
order by
  r.rdb$relation_name
При его выполнении в IBExpert на таблицах с некорректными данными появляется сообщение "Invalid data cast". В нашем случае неверная дата находилась в поле documentdate где-то в таблице gd_document. Далее, с помощью прокрутки результата запроса:
select id, documentdate from gd_document order by id
выходим на запись, соседнюю с проблемной. Сама плохая запись не может быть прочитана — кидает ошибку. Убираем из запроса поле documentdate и определяем id нужной нам записи. Затем, или удаляем ее, или присваиваем полю корректное значение.

1 мая 2011 г.

17 апр. 2011 г.

Редактор CSV файлов

При записи в CSV файл Microsoft Excel не сохраняет пустые колонки, если они находятся в конце записи. Как на беду, наша процедура универсального импорта требует строгого соответствия количества полей заданной спецификации. С помощью Гугла легко нашелся автономный бесплатный редактор CSV файлов с широчайшими возможностями.
Как и многие другие замечательные программы, CSVed написан на Borland Inprise Borland CodeGear Embarcadero Delphi.