WITH RECURSIVE
ns_tree AS (
SELECT
f.filename,
CAST((f.xid || '_' || f.dbid) AS VARCHAR(1024)) AS path,
l2.uses_xid,
l2.uses_dbid
FROM
at_namespace_file f
JOIN at_namespace_file_link l
ON l.uses_xid = f.xid AND l.uses_dbid = f.dbid
LEFT JOIN at_namespace_file_link l2
ON l2.filename = f.filename
WHERE
l.filename = :filename
UNION ALL
SELECT
f.filename,
(t.path || '-' || f.xid || '_' || f.dbid)
AS path,
l.uses_xid,
l.uses_dbid
FROM
ns_tree t
JOIN at_namespace_file f
ON t.uses_xid = f.xid AND t.uses_dbid = f.dbid
JOIN at_namespace_file_link l
ON l.filename = f.filename
WHERE
POSITION ((f.xid || '_' || f.dbid)
IN t.path) = 0)
SELECT
*
FROM
ns_tree
Таблица at_namespace_file содержит список объектов, а at_namespace_file_link -- связи между ними. Вычисление пути (path) и дополнительная проверка через функцию POSITION позволяют избежать зацикливания на кольцевых ссылках, если такие попадутся в исходных данных.
14 сент. 2013 г.
Список объектов в соответствии с заданными зависимостями
Если в предыдущем примере мы ранжировали заданный список объектов, то следующий пример возвращает упорядоченный в соответствии с иерархией зависимости список объектов, от которых зависит указанный объект.
Labels:
SQL
7 сент. 2013 г.
Firebird 2013 Tour
Firebird Project is glad to announce Firebird 2013 Tour – series of seminars around the world, devoted to Firebird, with members of Firebird Project as speakers. The first seminar will be in Siegburg (North Rhine-Westphalia, Germany), November 22, 2013.
Labels:
Firebird
2 сент. 2013 г.
Удаление гланд автогеном...
Таблицу со строковым первичным ключем подключить к визуальным контролам Гедымина нельзя, так как все они поголовно спроектированы для работы с целочисленными идентификаторами. Выход -- добавить вычисляемую колонку в запрос, которую заполнять хэшем от строкового значения. Встроенная функция Firebird HASH() возвращает 64-х битное целое (тип BIGINT), которое следует сдвигать вправо, пока значение не войдет в допустимый для 32-х битных целых диапазон.
В следующем примере мы генерируем ключи типа INTEGER по наименованиям контактов (что не совсем корректно, так как сами наименования у нас могут быть неуникальными).
select
cast(iif(log(2, hash(name)) > 30,
bin_shr(hash(name),
cast(log(2, hash(name)) as integer) - 30),
hash(name)) as integer),
name
from
gd_contact
В некоторых случаях может подойти и заполнение колонки последовательными значениями генератора:
select gen_id(my_gen, 1), name from gd_contact
Labels:
SQL
1 сент. 2013 г.
Построение списка зависимых объектов
Замечательная задача для проверки программиста на знание SQL и реляционных БД. Пусть в одной таблице хранится список объектов. Объекты могут зависеть друг от друга. Связи хранятся в другой таблице ввиде пар ключей: объект - объект, от которого зависит данный объект. Требуется построить упорядоченный список, чтобы для любого объекта в нем, все объекты, от которых он зависит, располагались перед ним.
Решение с использованием рекурсивного CTE:
WITH RECURSIVE
ns_tree AS (
SELECT
n.filename AS headname,
0 AS usescount,
CAST((n.xid || '_' || n.dbid) AS VARCHAR(1024)) AS path,
n.filename
FROM
at_namespace_file n
UNION ALL
SELECT
t.headname,
(t.usescount + 1) AS usescount,
(t.path || '-' || n.xid || '_' || n.dbid) AS path,
n.filename
FROM
ns_tree t
JOIN at_namespace_file_link l
ON l.filename = t.filename
JOIN at_namespace_file n
ON l.uses_xid = n.xid and l.uses_dbid = n.dbid
WHERE
POSITION ((n.xid || '_' || n.dbid) IN t.path) = 0
)
SELECT
t.headname, sum(t.usescount)
FROM
ns_tree t
GROUP BY
1
ORDER BY
2
В приведенном запросе at_namespace -- список объектов, а at_namespace_link -- связи между ними. Вычисление пути (path) и дополнительная проверка через функцию POSITION позволяют избежать зацикливания на кольцевых ссылках, если такие попадутся в исходных данных.
Labels:
исходный код,
программирование,
школа,
SQL
Предупрежден -- значит вооружен!
Контроллеры Marvell 88SE91xx и HDD > 2.2TB (3TB, 4TB).
Labels:
цікава
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).
Что мы видим из данного примера?
-
Необходим класс для доступа к Прологу из макросов. Далее по тексту будем называть его PL. Экземпляр данного класса создается стандартным образом через глобальный объект Designer/Creator. Каждый экземпляр может иметь свое имя.
PL должен иметь метод для формирования предикатов на основании заданной SQL выборки. Пример кода:
... Call PL.MakePredicates(_ "SELECT id, citykey, name FROM gd_contact", _ gdcBaseManager.ReadTransaction, _ "gd_contact", "name") ...Последний параметр -- имя выборки, которое будет использоваться для формирования имени .pl файла в режиме отладки. Пусть это и не касается непосредственно сопряжения Пролога с Гедымином, но здесь стоит вспомнить об идее изоляции разработчика от работы с SQL запросами и инкапсуляции последних внутрь т.н. SQL объекта. SQL объект -- это заранее написанный, проверенный и оптимизированный SQL запрос, загружаемый на базу стандартным образом через настройки или пространства имен. Для выполнения, программист обращается к нужному SQL объекту по его РУИДу. PL должен иметь метод для формирования предикатов на основании бизнес-класса. На вход передается класс-подтип, подмножество, дополнительные условия выборки. Сразу следует договориться о стандартном механизме (способе) загрузки данных мастер-дитэйл (например, документ накладная с позициями).
... Call PL.MakePredicates2(_ "TgdcCompany", "", "ByID", Array(777777), "", _ gdcBaseManager.ReadTransaction, _ "gd_contact", "name") ...PL должен иметь метод для формирования предикатов на основании существующего набора данных (дата-сета). PL должен иметь метод для ручного формирования произвольных предикатов. PL должен иметь метод для вычисления цели. Результат вычисления может быть как одиночное значение, так и выборка. Для работы с последней предусмотрены методы итерации (EOF, First, Next) и методы для обращения к параметрам по имени. С помощью соответствующих методов результат вычисления может быть напрямую помещен в указанную таблицу в базе, клиент-датасет в оперативной памяти, или на его основе могут быть созданы новые бизнес-объекты в БД. Предикаты, которые создает разработчик, должны храниться в базе данных аналогично тому, как сейчас хранится код VBScript. В дереве Проводника Редактора скрипт-объектов следует добавить корневой раздел для кода на Прологе. Внутри раздела пролог-скрипты могут размещаться в папках. Минимальная единица для загрузки в объект PL -- один пролог-скрипт. Каждый скрипт имеет уникальное имя и РУИД. Загрузка осуществляется по РУИДу. Внутри скрипта могут встречаться директивы %#INCLUDE для загрузки других пролог-скриптов (аналогично директиве '#INCLUDE для VBScript). Стандартные библиотеки SWI-Prolog, которые в дистрибутиве занимают 8 Мб в 377 файлах, будут храниться в базе данных точно так же, как и обычные пролог-скрипты. Отладка:
-
Для отладки на компьютере должен быть установлен полный вариант SWI-Prolog и, возможно, SWI-Prolog Editor.
Местоположение SWI-Prolog и каталога для временных файлов задается в параметрах платформы.
Режим отладки активизируется в параметрах редактора скрипт-объектов для списка конкретных экземпляров PL, заданных их именами. Если список пуст, то режим активируется для всех PL объектов.
Когда активирован режим дебаггера предикаты записываются в текстовые файлы .pl программ во временном каталоге. При этом файлы формируются следующим образом:
-
Для каждого пролог-скрипта отдельный файл.
Результаты вызова MakePredicatesX помещаются в файлы в соответствии с заданными именами.
Labels:
архитектура,
идеи,
prolog,
SQL
17 авг. 2013 г.
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. Может в этом и был когда-то какой-то смысл, но я решительно ничего не могу вспомнить.
Пока поменяем в скриптах генерации эталона. Если ничего не вылезет можно будет апдейт сделать и для существующих баз.
Labels:
база данных,
оптимизация
10 авг. 2013 г.
Подписаться на:
Сообщения (Atom)

