29 авг. 2013 г.

Подключение Embedded SWI-Prolog в Гедымин

Есть два варианта подключения Пролога. Первый -- мы обращаемся к embedded SWI-Prolog из кода на VBScript через глобальный объект (назовем его PL). Второй -- алгоритм пишется непосредственно на Прологе, а доступ к функционалу платформы происходит через Foreign Predicates.

Обращение к Прологу через глобальный объект мы рассмотрим на сравнительном примере доступа к реляционным данным из макроса на Гедымине. Пусть данные находятся в двух таблицах: GD_CONTACT(ID, CITYKEY, NAME) и GD_PLACE(ID, NAME):

ID  CITYKEY  NAME
======================
1   1        Company A
2   1        Company B
3   2        Company C

ID  NAME
======================
1   Minsk
2   Berioza 
Для извлечения cписка компаний по заданному наименованию города мы пишем SQL запрос, который выполняем через объект класса TIBSQL:
...
Dim q
Set q = Creator.GetObject(nil, "TIBSQL", "")
Set q.Transaction = gdcBaseManager.ReadTransaction
q.SQL.Text = _
  "SELECT c.name " & _
  "FROM gd_contact c JOIN gd_place p " & _
  "  ON p.id = c.citykey " & _
  "WHERE p.name = 'Minsk' "
q.ExecQuery
While Not q.EOF 
  ...
  q.Next
WEnd 
...
Теперь изобразим тоже самое на Prolog.

Исходные данные в виде предикатов Prolog выглядят так:

gd_contact(1, 1, 'Company A').
gd_contact(2, 1, 'Company B').
gd_contact(3, 2, 'Company C').

gd_place(1, 'Minsk').
gd_place(2, 'Berioza').
Правило связи компании с городом через ключи:
bycity(City, Name) :- 
  gd_place(CityID, City),
  gd_contact(_, CityID, Name).
Тогда запрос на извлечение всех минских компаний будет выглядеть следующим образом:
? bycity('Minsk', Name).
Что мы видим из данного примера?

  1. Необходим класс для доступа к Прологу из макросов. Далее по тексту будем называть его PL. Экземпляр данного класса создается стандартным образом через глобальный объект Designer/Creator. Каждый экземпляр может иметь свое имя.
  2. PL должен иметь метод для формирования предикатов на основании заданной SQL выборки. Пример кода:
    ...
    Call PL.MakePredicates(_
      "SELECT id, citykey, name FROM gd_contact", _
      gdcBaseManager.ReadTransaction, _ 
      "gd_contact", "name")
    ...
    
    Последний параметр -- имя выборки, которое будет использоваться для формирования имени .pl файла в режиме отладки.

    Пусть это и не касается непосредственно сопряжения Пролога с Гедымином, но здесь стоит вспомнить об идее изоляции разработчика от работы с SQL запросами и инкапсуляции последних внутрь т.н. SQL объекта. SQL объект -- это заранее написанный, проверенный и оптимизированный SQL запрос, загружаемый на базу стандартным образом через настройки или пространства имен. Для выполнения, программист обращается к нужному SQL объекту по его РУИДу.

  3. PL должен иметь метод для формирования предикатов на основании бизнес-класса. На вход передается класс-подтип, подмножество, дополнительные условия выборки. Сразу следует договориться о стандартном механизме (способе) загрузки данных мастер-дитэйл (например, документ накладная с позициями).
    ...
    Call PL.MakePredicates2(_
      "TgdcCompany", "", "ByID", Array(777777), "", _
      gdcBaseManager.ReadTransaction, _ 
      "gd_contact", "name")
    ...
    
  4. PL должен иметь метод для формирования предикатов на основании существующего набора данных (дата-сета).
  5. PL должен иметь метод для ручного формирования произвольных предикатов.
  6. PL должен иметь метод для вычисления цели. Результат вычисления может быть как одиночное значение, так и выборка. Для работы с последней предусмотрены методы итерации (EOF, First, Next) и методы для обращения к параметрам по имени.
  7. С помощью соответствующих методов результат вычисления может быть напрямую помещен в указанную таблицу в базе, клиент-датасет в оперативной памяти, или на его основе могут быть созданы новые бизнес-объекты в БД.
  8. Предикаты, которые создает разработчик, должны храниться в базе данных аналогично тому, как сейчас хранится код VBScript.
  9. В дереве Проводника Редактора скрипт-объектов следует добавить корневой раздел для кода на Прологе. Внутри раздела пролог-скрипты могут размещаться в папках.
  10. Минимальная единица для загрузки в объект PL -- один пролог-скрипт. Каждый скрипт имеет уникальное имя и РУИД. Загрузка осуществляется по РУИДу. Внутри скрипта могут встречаться директивы %#INCLUDE для загрузки других пролог-скриптов (аналогично директиве '#INCLUDE для VBScript).
  11. Стандартные библиотеки SWI-Prolog, которые в дистрибутиве занимают 8 Мб в 377 файлах, будут храниться в базе данных точно так же, как и обычные пролог-скрипты.
  12. Отладка:
    1. Для отладки на компьютере должен быть установлен полный вариант SWI-Prolog и, возможно, SWI-Prolog Editor.
    2. Местоположение SWI-Prolog и каталога для временных файлов задается в параметрах платформы.
    3. Режим отладки активизируется в параметрах редактора скрипт-объектов для списка конкретных экземпляров PL, заданных их именами. Если список пуст, то режим активируется для всех PL объектов.
    4. Когда активирован режим дебаггера предикаты записываются в текстовые файлы .pl программ во временном каталоге. При этом файлы формируются следующим образом:
      • Для каждого пролог-скрипта отдельный файл.
      • Результаты вызова MakePredicatesX помещаются в файлы в соответствии с заданными именами.
    5. При вызове метода вычисления цели в режиме дебаггера загружается SWI-Prolog или SWI-Prolog Editor. В среду выполнения/отладки подгружаются созданные временные файлы.
    6. Гедымин ждет завершения работы процесса SWI-Prolog.
    7. После окончания отладки проверяются файлы для выгруженных пролог-скриптов. Если обнаружены изменения Гедымин предлагает загрузить их в базу данных.

17 авг. 2013 г.

В Редактор SQL добавлена вкладка Бизнес-классы:

Выбрав класс в списке можно перенести его SelectSQL в окно выполнения запроса или открыть форму просмотра.

PS: Знаю, знаю, фильтр не помешал бы. Но, и Вильня не сразу строилась.

16 авг. 2013 г.

Просмотр объекта по ссылке

Добавлено в Гедымин. Если в окне редактора SQL, в таблице с результатом выполнения запроса, установить курсор на поле-ссылку, то с помощью кнопок на панели инструментов (на рисунке ниже) можно: открыть объект на просмотр/изменение, удалить объект, открыть форму просмотра объекта.

15 авг. 2013 г.

Замечено на улицах Минска

Стэнсильная реклама Гедымина.
День сурка -- это 15 лет работы с молодыми программистами. Раз за разом приходится объяснять очевидные вещи. Например, что нельзя формировать SQL запрос из кусочков текста, используя функции преобразования DateToStr, FloatToStr и т.п. Указанные функции при форматировании результата используют локальные региональные установки, которые могут не совпадать с требованиями стандарта SQL. Так, Firebird понимает дату из строки вида 'dd.mm.yyyy', а на компьютере пользователя может быть установлен формат 'dd-mm-yyyy'. Хуже всего, когда на машине разработчика локальный формат удовлетворяет сервер, а на компьютере клиента -- нет.

С функциями конвертации типов понятно. А строки? Строки вставлять категорически запрещается. Во-первых, наличие одинарных кавычек во вставляемом значении приведет либо к синтаксической ошибке, либо к неверной выборке. Во-вторых, см. SQL Injection.

11 авг. 2013 г.

Вот почему у нас куча односимвольных типов объявлена как VARCHAR вместо CHAR? Ладно бы еще всякие там activity флажки в плане счетов, но признак дебет/кредит для записи проводки это никуда не годится. Десять миллионов проводок, двадцать миллионов записей в AC_ENTRY == сорок миллионов байт на хранение длины поля, которая всегда равна 1. Может в этом и был когда-то какой-то смысл, но я решительно ничего не могу вспомнить.

Пока поменяем в скриптах генерации эталона. Если ничего не вылезет можно будет апдейт сделать и для существующих баз.

10 авг. 2013 г.

Таки дождались: Delphi for Android в стадии бета теста.

8 авг. 2013 г.

Знакомая картина

Австралийский штат Квинсленд запретил IBM заключать договора на внедрение ПО, так как компания завалила внедрение расчета зарплаты для местного отдела здравоохранения. Проект тянется с 2007 года. За это время стоимость выросла с начальных 10 миллионов до 1.2 млрд австралийских долларов.
“IBM will not be allowed to enter any new contracts with the State Government until it improves its governance and contracting practices,” the statement read. Newman said the company must prove it has dealt with past misconduct and will prevent future misconduct.
Тендеры, что в Австралии, что в Беларуси, везде проводятся одинаково:
Specifically, it found that IBM received favourable information during the contract procurement process that helped it win the initial contract unfairly, that the company may have low-balled its bid based on that information...

Первые шаги в функциональном программировании

Двадцать лет назад я собирался изучить Prolog. Купил даже книгу Ивана Братко "Программирование на языке Пролог для искусственного интеллекта". Так бы она и пылилась на полке, если бы не Гедымин и очередной наш технологический прорыв на стыке пост-реляционных технологий и функционального программирования.

А вот и собственноручно написанный код. Решение первой задачи Проекта Ойлера:

my_sum(From, To, C, C2, S) :-
  From < To,
  ( From mod C =:= 0; From mod C2 =:= 0 ),
  Next is From + 1,
  my_sum(Next, To, C, C2, T),
  S is T + From.
my_sum(From, To, C, C2, S) :-
  From < To,
  From mod C =\= 0,
  From mod C2 =\= 0,
  Next is From + 1,
  my_sum(Next, To, C, C2, T),
  S is T.
my_sum(From, To, _, _, S) :-
  From = To,
  S is 0.
PS: Надо же: Леонард Ойлер оказывается родился в Базеле ))

Бразилия первая не только в футболе

Сколько из 16 414 инстоляций в Беларуси сделано благодаря Гедымину? Статистика по загрузкам сервера Firebird c официального сайта. Даже если ориентироваться на эту заниженную статистику и принять, что в среднем сервер обслуживает 10 конектов, то стоимость такого же количества лицензий платного сервера Interbase составит 2 262 000 000 EUR. Впечатляет.