Одни наши клиенты, крупное промышленное предприятие, в ожидании комплексной проверки задумались о переходе на бесплатный Open Office. А мне вспомнились времена, когда приобретение легального программного обеспечения не представляло большой проблемы для предприятия, хотя лицензии тогда никто не проверял. После падения железного занавеса, в первой половине девяностых, американские компании пытались освоить местный рынок. Некоторые даже локализовывали свои продукты, но большинство поставляло обычные англоязычные версии по сниженым в разы ценам.
У организации, на которую мы тогда работали, на сеть из десяти компьютеров было приобретено десять копий Microsoft Windows for Workgroups 3.11 и одна коробка с Microsoft Windows 3.1. Последняя использовалась вообще считанное число раз и в основном для раскладки пасьянса.
На большой полке размещались коробки от средств разработки: Turbo Pascal 6.0, Borland Pascal 7.0, Paradox Engine 1.0, Borland Paradox 1.0 for Windows и Borland Delphi.
Надо заметить, что для покупки легального программного обеспечения тогда существовал серьезный стимул. В то время, как в книжных магазинах продавалось целых две книги по программированию, в коробке с программой шел полный комплект: руководство пользователя, руководство разработчика, руководство по отладке и т.п. Кое-что, позже и в переводе, можно было выловить на BBS и распечатать на матричном принтере, но, разумеется это не шло ни в какое сравнение с оригинальной книгой, качественно напечатанной на снежно белой бумаге.
На сегодняшний день, цены на ПО для Беларуси не отличаются от цен для всего остального мира. Как мне представляется, здесь западные компании просто недопонимают сложившуюся ситуацию и совершают большую ошибку. Снизив цену в 4-5 раз они могли бы в десятки раз повысить продажи и одним махом решить проблему пиратства.
27 февр. 2011 г.
18 февр. 2011 г.
Проверка прав на уровне записи
Разборка одного случая, когда запрос под Администратором выполнялся значительно быстрее чем под обычным пользователем, показала, что вина лежит на дополнительном условии с вызовом функции G_SEC_TEST.
Появление UDF функции в секции WHERE запроса часто сводит с ума оптимизатор и приводит к ужасным планам. Если проверку на права доступа перенести на уровень клиента, внутрь датасета, сразу после считывания записи с сервера и перед копированием ее во внутренний буфер, то получим выигрыш в тех случаях, когда у пользователя есть права на большинство записей в результате выборки. В противном случае — перенос проверки на клиента породит избыточный трафик по сети.
Слаще ли хрен редьки выяснить можно только экспериментальным путем.
Вот, если бы заранее знать долю записей на которые у текущего пользователя есть/отсутствуют права...
Появление UDF функции в секции WHERE запроса часто сводит с ума оптимизатор и приводит к ужасным планам. Если проверку на права доступа перенести на уровень клиента, внутрь датасета, сразу после считывания записи с сервера и перед копированием ее во внутренний буфер, то получим выигрыш в тех случаях, когда у пользователя есть права на большинство записей в результате выборки. В противном случае — перенос проверки на клиента породит избыточный трафик по сети.
Слаще ли хрен редьки выяснить можно только экспериментальным путем.
Вот, если бы заранее знать долю записей на которые у текущего пользователя есть/отсутствуют права...
Labels:
безопасность,
идеи
13 февр. 2011 г.
Замена парсера SQL
Существующий парсер SQL называется TsqlParser и используется внутри класса TatSQLSetup из модуля at_sql_setup.pas. TatSQLSetup отвечает за формирование запросов SELECT, UPDATE, INSERT внутри бизнес-объекта. На момент написания кода бизнес-объекта в Delphi, разработчик не знает какие поля будут позже добавлены настройщиком системы. Поэтому он пишет например так:
Во время выполнения программы, после создания экземпляра бизнес-объекта, в процессе его открытия (не забываем, что БО является набором данных, т.н. датасетом), происходит последовательная разборка запроса, добавление списка пользовательских полей (для ссылок добавляются джоины на справочники), и обратная сборка запроса. Информация о пользовательских полях и их типах берется из глобального объекта atDatabase.
То ли существующий парсер работает достаточно медленно, то ли все дело в обращении к объекту atDatabase (точных замеров не производилось), после формирования запроса он кэшируется и создаваемые позже объекты такого же типа используют уже готовый текст запроса из кэша.
Собственно, задание:
SELECT
*
FROM
gd_contact z JOIN gd_people p
ON p.contactkey = z.id
Напоминаем, что главная таблица бизнес-объекта у нас всегда имеет алиас z. Во время выполнения программы, после создания экземпляра бизнес-объекта, в процессе его открытия (не забываем, что БО является набором данных, т.н. датасетом), происходит последовательная разборка запроса, добавление списка пользовательских полей (для ссылок добавляются джоины на справочники), и обратная сборка запроса. Информация о пользовательских полях и их типах берется из глобального объекта atDatabase.
То ли существующий парсер работает достаточно медленно, то ли все дело в обращении к объекту atDatabase (точных замеров не производилось), после формирования запроса он кэшируется и создаваемые позже объекты такого же типа используют уже готовый текст запроса из кэша.
Собственно, задание:
- В классе TatSQLSetup заменить старый парсер на новый.
Откомпилированную грамматику Firebird SQL подлинковать к экзешнику ввиде двоичного ресурса.
Проверить быстродействие нового парсера и, возможно, отказаться от кэширования сформированного текста запроса.
Код, использующий новый парсер, отделить от существующего условной компиляцией под символом NEW_SQL_PARSER.
Labels:
SQL
10 февр. 2011 г.
Лучше поздно, чем никогда
Бывают такие баги/нюансы программного обеспечения, которые портят пользователям тонны крови, а исправить их, как оказывается в итоге, -- минутное дело. Но, всегда то руки не доходят, то лень, то нет времени, то религиозные ограничения не позволяют.
Вот и Микрософт по прошествии 16-ти лет отключила-таки автозапуск в операционной системе Windows XP. Впервые представленная еще в Windows 95 функция, служит лазейкой для, как минимум, 90% всех заражений компьютерными вирусами.
Вот и Микрософт по прошествии 16-ти лет отключила-таки автозапуск в операционной системе Windows XP. Впервые представленная еще в Windows 95 функция, служит лазейкой для, как минимум, 90% всех заражений компьютерными вирусами.
Атрибуты визуального отображения
Пусть бизнес-объект для текущей записи, в зависимости от значений полей, возвращает набор визуальных атрибутов. Например: normal, grayed, strong, accented и т.п. При отрисовке строки, грид будет брать из текущей визуальной темы шрифт, цвет фона и т.п. в соответствии с атрибутами бизнес-объекта. Тогда мы сможем управлять внешним видом данных в соответствии с природой конкретного бизнес-объекта. Так, для объекта пользователь системы, учетные записи из группы Администраторы можно выводить жирным шрифтом. В списке счетов-фактур можно выделять просроченные, оплаченные, частично оплаченные и т.д.
1 февр. 2011 г.
ORM с помощью updateable view
Бизнес-объекты скрывают от программиста реляционную структуру данных конкретной сущности (т.н. ORM). Например, последовательность методов Insert-заполнение полей-Post объекта типа TgdcCompany приведет к трем операциям INSERT в базу данных внутри метода InternalPostRecord, в таблицы gd_contact, gd_company и gd_companycode.
Такого же эффекта можно достичь средствами одного только SQL, используя обновляемые представления (updateable view).
Создадим представление для отображения данных бизнес-объекта Компания:
Такого же эффекта можно достичь средствами одного только SQL, используя обновляемые представления (updateable view).
Создадим представление для отображения данных бизнес-объекта Компания:
create view vcompany as
select * from
gd_contact c
join gd_company co on c.id=co.contactkey
left join gd_companycode cc on cc.companykey = c.id
Создадим триггер:recreate trigger vcompany_ai for vcompany
after insert
position 0
as
declare variable id integer;
begin
if (NEW.id IS NULL) then
id = GEN_ID(gd_g_unique, 1);
else
id = NEW.id;
insert into gd_contact (id, parent, contacttype, name)
values (:id, NEW.parent, 3, NEW.name);
insert into gd_company (contactkey, fullname)
values (:id, NEW.name);
end
Теперь добавить компанию в базу данных можно с помощью команды:insert into vcompany (name, parent)
values ('Company name', some_existing_folder_id)
Аналогичным образом реализуем обновление и удаление данных.
31 янв. 2011 г.
Бухгалтерские проводки как функция, а не данные
У нас документы хранятся отдельно от проводок. Как уже упоминалось в этом блоге, проводки (т.е. записи в таблицы ac_entry и ac_record) формируются алгоритмами типовых проводок. В результате получаем две огромные таблицы большая часть информации в которых дублирует gd_document и данные из соответствующих документов.
Если вместо формирования VBScript-а типовой проводки формировать код selectable процедуры, которая на основании данных документов сформирует список проводок, то:
Если вместо формирования VBScript-а типовой проводки формировать код selectable процедуры, которая на основании данных документов сформирует список проводок, то:
- Избавляемся от таблиц ac_entry и ac_record.
- Избавляемся от таблицы gd_document (на вскидку, три указанные таблицы с индексами занимают не менее четверти объема любой базы данных).
- Избавляемся от ограничения на количество аналитических признаков. Так как проводки являются просто отображением таблицы с документами, то любое поле этой таблицы сразу становится аналитическим признаком. Более того, поле ссылка? Тогда каждое поле указываемой таблицы может быть аналитикой и так до бесконечности. Журнал ордер по продажам с группировкой не по самим клиентам, а по областям/районам можно будет построить всего за несколько кликов мышкой.
- Избавляемся от системы количественных показателей в проводках. При необходимости вести учет одновременно в нескольких единицах измерения следует определить функцию пересчета (отображения) основной единицы в дополнительные.
- Избавляемся от проблемы рассинхронизации данных документов и соответствующих им проводок. Никаких больше "перепровести проводки".
- Ускоряем запись и изменение документов.
- Избавляемся от бизнес-объектов типа Проводка, которые бизнес-объектами в полном смысле этого слова не являются.
- Возможно, упрощается репликация данных.
Labels:
идеи
Firebird 3.0 как сервер приложения?
Алгоритмы формирования типовых хозяйственных операций и проводок у нас хранятся в двоичном виде как последовательность программных блоков. Данная последовательность преобразуется в код на VBScript перед выполнением (или при сохранении, что не столь важно). Что, если мы будем преобразовывать двоичный код в текст триггера Firebird на события AFTER INSERT и AFTER UPDATE для таблицы документа?
Получаем профит ввиде разгрузки клиента и перемещения логики приложения на сервер. Единственная проблема с блоками произвольного кода, где настройщик мог вставить обращения к объектам платформы и бизнес-объектам. Для таких случаев можно развить механизм, чтобы он в зависимости от ситуации работал и по-новому, и по-старому. Если возможно — выполняется приобразование в триггер, нет — работает код на VBScript.
Получаем профит ввиде разгрузки клиента и перемещения логики приложения на сервер. Единственная проблема с блоками произвольного кода, где настройщик мог вставить обращения к объектам платформы и бизнес-объектам. Для таких случаев можно развить механизм, чтобы он в зависимости от ситуации работал и по-новому, и по-старому. Если возможно — выполняется приобразование в триггер, нет — работает код на VBScript.
29 дек. 2010 г.
17 дек. 2010 г.
Сокращения на Yahoo!
Yahoo! закрывает delicious.com (и некоторые другие сервисы). Надеюсь они предоставят возможность слить ссылки. Обидно будет потерять все, что нажито непосильным трудом :(
PS: Привет Романчуку. Не всегда инвестор заинтересован в развитии и сохранении приобретенного предприятия. Бывает и так: поматросили и бросили.
PS: Привет Романчуку. Не всегда инвестор заинтересован в развитии и сохранении приобретенного предприятия. Бывает и так: поматросили и бросили.
Labels:
интернет
13 дек. 2010 г.
По дороге к унифицированному парсеру SQL запросов
Создатели SQL похоже всерьез надеялись, что каждая кухарка со знанием английского будет писать запросы к реляционным базам. Чем еще объяснить такое буйство синтаксисов для некоторых функций? Все эти EXTRACT(year FROM date), DATEADD(month 5 TO date) и т.п. Странно, что для функции BIN_AND оставили синтаксис BIN_AND(a, b), а не придумали что-нибудь вроде BIN_AND(a AND b). Или возьмем синтаксическую избыточность многих конструкций и наличие необязательных зарезервированных слов. Например, SELECT [ALL] * FROM..., column [AS] alias... Простым разработчикам SQL парсеров от этого теперь одна головная боль.
Labels:
SQL
2 дек. 2010 г.
Лечение поврежденной БД под Firebird 2.0
От клиентов пришла поврежденная база. Сервер Firebird 2.0. Внешне все ОК: gbak и gfix проходят без проблем, но некоторые хранимые процедуры не перекомпилируются (ALTER PROCEDURE) и не удаляются с сообщением:
Соответственно, невозможен процесс апгрейда базы с помощью утилиты FDBConvert.
Вылечить базу получилось следующим образом:
UPD: Конкретно в этой базе проблемы были с процедурами: MSG_P_GETCHILDCOUNT_BOX, MSG_P_EXPANDLIMIT_BOX, MSG_P_RESTRUCT_BOX.
This operation is not defined for system tables.
unsuccessful metadata update.
cannot delete.
COLUMN RDB$220.
there are 1 dependencies.
Соответственно, невозможен процесс апгрейда базы с помощью утилиты FDBConvert.
Вылечить базу получилось следующим образом:
- Определили список поврежденных процедур
- Для каждой из них сохранили исходный текст
- Удалили параметры процедуры с помощью запроса
DELETE FROM rdb$procedure_parameters WHERE rdb$procedure_name = 'name' - Удалили процедуру (DROP PROCEDURE)
UPD: Конкретно в этой базе проблемы были с процедурами: MSG_P_GETCHILDCOUNT_BOX, MSG_P_EXPANDLIMIT_BOX, MSG_P_RESTRUCT_BOX.
Labels:
fdbconvert,
Firebird
Подписаться на:
Сообщения (Atom)