UDF, NUMERIC,DOUBLE PRECISION

IBX, FIBPlus, UIB, ADO, .Net и прочее-прочее-прочее, в общем все, что относится к созданию приложений, работающих с InterBase, Firebird и Yaffil - клиент-серверных, трехзвенных, консольных и т.п.

Модератор: kdv

Ответить
stix-s
Заслуженный разработчик
Сообщения: 557
Зарегистрирован: 13 дек 2005, 11:52

UDF, NUMERIC,DOUBLE PRECISION

Сообщение stix-s » 15 авг 2006, 11:50

наваял я UDF, которая возвращает мне сумму прописью ради эксперимента объявил ее по разному
1-

Код: Выделить всё

DECLARE EXTERNAL FUNCTION SUMTOTEXT
    NUMERIC(15,
    2),
    INTEGER,
    CSTRING(2048)
RETURNS CSTRING(2048)
ENTRY_POINT 'TextSumm' MODULE_NAME 'All_my_udf'
2-

Код: Выделить всё

DECLARE EXTERNAL FUNCTION SUMTOTEXT2
    DOUBLE PRECISION,
    INTEGER,
    CSTRING(2048)
RETURNS CSTRING(2048)
ENTRY_POINT 'TextSumm' MODULE_NAME 'All_my_udf'
при выполнении запроса

Код: Выделить всё

select first 1
sumtotext(123456789.33,1,'XXXXXXX'),
sumtotext2(123456789.33,1,'XXXXXXX')
 from gorod
получаются весьма разные результаты :(
sumtotext=Шесть рублей 09 копеек
sumtotext2=Сто двадцать тpи миллиона четыреста пятьдесят шесть тысяч семьсот восемьдесят девять рублей 33 копейки
в первом случае в функцию передается значение 6.09......Е-304
во втором - то, что надо
фунция писана в дельфях и сумму принимает, как
function TextSumm(MySum:PDouble;show_00_kop:Pinteger;ResCHR:PChar): PChar; cdecl; export;
результат возвертается в ResCHR
не нравится функции, когда я в качестве параметра ей NUMERIC(15,
2) скармливаю, а ведь в базе так и планирую денежные величины хранить
гдеж я накривил-то?

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 15 авг 2006, 12:28

наваял я UDF, которая возвращает мне сумму прописью ради эксперимента объявил ее по разному
у тебя диалект какой?

в любом случае, в объявлении udf могут быть только физические типы. numeric/decimal - маппируемый тип, в зависимости от разрядности и диалекта.
MySum:PDouble;show_00_kop:Pinteger;ResCHR:PChar
ты сюда заглядывал?
www.ibase.ru/devinfo/udf_ok.htm
а сюда?
http://www.ibase.ru/devinfo/udf_safe.htm

stix-s
Заслуженный разработчик
Сообщения: 557
Зарегистрирован: 13 дек 2005, 11:52

Сообщение stix-s » 15 авг 2006, 12:46

kdv писал(а): у тебя диалект какой?
пардон, диалект 3 FB 1.5.3
kdv писал(а):в любом случае, в объявлении udf могут быть только физические типы. numeric/decimal - маппируемый тип, в зависимости от разрядности и диалекта.
следовательно придется так делать:

Код: Выделить всё

select sumtotext(cast(field as double precision)) from table,
где field NUMERIC(15, 2)
 
Угумс, сейчас снова перечитываю.
смущает немного
3. возврат строки, которая является входным параметром. Это "трюк", поскольку IB сам аллокирует память для входного параметра. Основные неудобства - размер выходной строки должен совпадать с размером входной, и невозможность использования этого метода если функция не содержит входных строковых параметров (или по типу эти параметры отличаются).
но, полагаю, что память выделяется по указанному размеру параметра, в моем случае 2048 байт, а не по фактическому размеру параметра, так что ИМХО, если выходная строка не больше входа, то вроде как ничего страшного нет
Последний раз редактировалось stix-s 15 авг 2006, 12:56, всего редактировалось 1 раз.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 15 авг 2006, 12:54

пардон, диалект 3 FB 1.5.3
ну так ёшкин кот, с чего ты взял, что numeric(15,2) в третьем диалекте это double precision? :)
следовательно придется так делать:
следовательно, надо написать udf, в которую передается int64, а не double precision. и почитать про разницу между целыми и вещественными числами :)

stix-s
Заслуженный разработчик
Сообщения: 557
Зарегистрирован: 13 дек 2005, 11:52

Сообщение stix-s » 15 авг 2006, 13:06

kdv писал(а): следовательно, надо написать udf, в которую передается int64, а не double precision. и почитать про разницу между целыми и вещественными числами :)
почитать, никада не откажусь :)
только вот куды мне в INT64 копейки деть? :)

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 15 авг 2006, 13:10

только вот куды мне в INT64 копейки деть?
еще раз - в третьем диалекте numeric любой размерности хранится только в виде целых чисел - smallint, integer, int64.

stix-s
Заслуженный разработчик
Сообщения: 557
Зарегистрирован: 13 дек 2005, 11:52

Сообщение stix-s » 15 авг 2006, 13:29

kdv писал(а): еще раз - в третьем диалекте numeric любой размерности хранится только в виде целых чисел - smallint, integer, int64.
понял я, однако засада :(

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 15 авг 2006, 14:18

Интересно, зачем было изобретать

Код: Выделить всё

function TextSumm(MySum: PDouble; show_00_kop: Pinteger; ResCHR: PChar): PChar; cdecl; export;
если везде пишут

Код: Выделить всё

function TextSumm(var MySum: Double; var show_00_kop: Integer; ResCHR: PChar): PChar; cdecl; export;

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 15 авг 2006, 14:23

Не у всех хватает мужества закладываться на слабодокументированные фичи - такие как способ передачи переменных по ссылке.

stix-s
Заслуженный разработчик
Сообщения: 557
Зарегистрирован: 13 дек 2005, 11:52

Сообщение stix-s » 15 авг 2006, 15:15

Dimitry Sibiryakov писал(а):Не у всех хватает мужества закладываться на слабодокументированные фичи - такие как способ передачи переменных по ссылке.
мммммм, эт намек - типа не связывайся? или связывайся, но с тщательной оглядкой? :)
мне как-то больше всего понравилось ч/з входной параметр строки вовращать

stix-s
Заслуженный разработчик
Сообщения: 557
Зарегистрирован: 13 дек 2005, 11:52

Сообщение stix-s » 15 авг 2006, 15:18

WildSery писал(а):Интересно, зачем было изобретать

Код: Выделить всё

function TextSumm(MySum: PDouble; show_00_kop: Pinteger; ResCHR: PChar): PChar; cdecl; export;
если везде пишут

Код: Выделить всё

function TextSumm(var MySum: Double; var show_00_kop: Integer; ResCHR: PChar): PChar; cdecl; export;
кхм, могет ты тож по ссылкам пройдешься, что мне кдв рекомендовал?
и где это - везде? :)

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 15 авг 2006, 16:51

мммммм, эт намек - типа не связывайся? или связывайся, но с тщательной оглядкой?
это намек, что перед тем как сочинять свою udf, неплохо посмотреть udf на сайте в качестве примеров.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 16 авг 2006, 15:18

stix-s писал(а):кхм, могет ты тож по ссылкам пройдешься, что мне кдв рекомендовал?
и где это - везде? :)
Что ж. Давай пройдусь, раз настаиваешь.

Код: Выделить всё

function Add_A(var iSmall: SmallInt; var iLong: Integer): Integer; cdecl; export;
Где тут PSmallint или PInteger? Везде var. Что хоть и имеет тот же смысл, но ^Integer усложняет восприятие кода.
Насчёт выходного параметра - да, если по ссылке, то без PInteger не обойтись. Но тут же смотрим:
с серверами архитектуры SuperServer нельзя использовать такие udf ... В SuperServer значения можно возвращать только по значению ...
Можно, конечно, с dll всегда класть readme.txt с содержимым "Никогда не использовать на SS!!!", но если решение очевидно, зачем так делать?

stix-s
Заслуженный разработчик
Сообщения: 557
Зарегистрирован: 13 дек 2005, 11:52

Сообщение stix-s » 17 авг 2006, 06:19

WildSery писал(а):function Add_A(var iSmall: SmallInt; var iLong: Integer): Integer; cdecl; export;[/code]Где тут PSmallint или PInteger? Везде var. Что хоть и имеет тот же смысл, но ^Integer усложняет восприятие кода.
Вот и я про тоже - результат тот же, только вид сбоку :)
Примечание: все передаваемые в UDF параметры всегда передаются по ссылке, т.е. должны быть объявлены как var или как указатели.
Лично для меня код прозрачнее, если кому-то захочется переделать - да за ради бога, мне исходника не жалко :) дело вкуса
правда для этой функции он до безобразия корявый ибо я его просто тупо с VBA переделал.
WildSery писал(а): Насчёт выходного параметра - да, если по ссылке, то без PInteger не обойтись.
1 - если посмотреть на объявления функции вверху - то видно, что первые два параметра ВХОДНЫЕ и ничего не возвращают.
с серверами архитектуры SuperServer нельзя использовать такие udf ... В SuperServer значения можно возвращать только по значению ...
2 - внимательно! Речь идет именно о ВОЗВРАТЕ! при условии использования глобальной переменной!
Скажем возвращать результат ч/з входной параметр тебе никто не запрещает :)
В SuperServer значения можно возвращать только по значению, по FREE_IT, или через входной параметр (см. дальше).
если уж цитировать, то полностью, а то смысл совершенно другой :)
WildSery писал(а): Можно, конечно, с dll всегда класть readme.txt с содержимым "Никогда не использовать на SS!!!", но если решение очевидно, зачем так делать?
неа, это не наш метод :) я как раз SS пользую :)
ЗЫ вообще-то дискуссия уже выходит за рамки вопроса :)

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 17 авг 2006, 11:14

2 stix-s:
Вижу, что ты так и недопонял, про что я говорю.
Я всего-навсего выразил своё отношение к использованию объектов-указателей, типа ^Integer, в программе, если есть более красивые и понятные не только пишущему этот код конструкции. И обосновал, что без них можно легко обходиться.

И раз уж ты завёл разговор... Использование всяких "хаков" и "фичей" типа использования для возврата входного параметра добавляет гордости кодеру за свои глубокие знания, но других никаких плюсов не добавляет, и даже наоборот, в последствии могут возникнуть минусы. Их использование ИМХО допустимо только в случае невозможности решения штатными средствами, или получения какого-либо существенного дополнительного бонуса в виде скорости работы или простоты реализации.

stix-s
Заслуженный разработчик
Сообщения: 557
Зарегистрирован: 13 дек 2005, 11:52

Сообщение stix-s » 17 авг 2006, 11:51

WildSery писал(а): Вижу, что ты так и недопонял, про что я говорю.
как еще прикажешь понять подобное цитирование?
WildSery писал(а): с серверами архитектуры SuperServer нельзя использовать такие udf ... В SuperServer значения можно возвращать только по значению ...
WildSery писал(а): Я всего-навсего выразил своё отношение к использованию объектов-указателей, типа ^Integer, в программе, если есть более красивые и понятные не только пишущему этот код конструкции. И обосновал, что без них можно легко обходиться.
Если кому-то не понравится, вполне можно переписать :)
WildSery писал(а): И раз уж ты завёл разговор... Использование всяких "хаков" и "фичей" типа использования для возврата входного параметра добавляет гордости кодеру за свои глубокие знания,
Никогда не заявлял, что слишком много знаю :) знал бы, вопросов бы тут не задавал :)
и с каких это пор возврат значения ч/з входной параметр стал
"хаком" или "фичей" ? :)
Все. в этой теме более не живу, ибо флейм :)
ЗЫ Спасибо всем, ответившим по существу вопроса.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 18 авг 2006, 11:53

stix-s писал(а):Если кому-то не понравится, вполне можно переписать :)
Мда. :( В нашем департаменте с таким отношением никто не задержится...
Без обид, к тебе никаких претензий, просто мысли вслух.
Извините за оффтоп.

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 18 авг 2006, 15:42

Добавлю свои пять копеек :).
[quote=stix-s]и с каких это пор возврат значения ч/з входной параметр стал
"хаком" или "фичей" ?[/quote]
С тех самых пор, как параметр назвался "входным". Использование данной возможности - дурной тон.

Ответить