powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Написание UDR
19 сообщений из 94, страница 4 из 4
Написание UDR
    #39384292
seertrue
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
__Avenger__А так:
Код: sql
1.
2.
3.
4.
5.
create function test_str (
    n1 varchar(255) CHARACTER SET UTF8
  ) returns varchar(255) CHARACTER SET UTF8
  external name 'udr!test_str'
  engine udr;



?

Это помогло, спасибо

Но база и так была создана в UTF8, посчитал что по умолчанию CHARACTER SET возьмется из базовый.
...
Рейтинг: 0 / 0
Написание UDR
    #39384296
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
seertrue,

ИХМО, с определением чарсета без явного указания оного в определении UDR есть косяки
...
Рейтинг: 0 / 0
Написание UDR
    #39384299
__Avenger__
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисseertrue,

ИХМО, с определением чарсета без явного указания оного в определении UDR есть косяки

Я вообще-то на два критерия намекал, 200 <> 255 и 4* (UTF8)
...
Рейтинг: 0 / 0
Написание UDR
    #39384301
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
__Avenger__,

это я просмотрел. Просто когда пробовал udr писать столкнулся с такой проблемой. Ну может сейчас уже всё норм. Это ещё на бете было.
...
Рейтинг: 0 / 0
Написание UDR
    #39385139
seertrue
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
__Avenger__
Я вообще-то на два критерия намекал, 200 <> 255 и 4* (UTF8)


В UDR реально ли передать строку более 255 используя такой метод выделения памяти (0 .. 4 * 255 - 1)?
Если нет то можно ли вообще?

во всяком случае
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
create or alter procedure GEN_ROWS (
    START_N integer,
    END_N integer)
returns (
    RESULT integer,
    BINRES double precision,
    STR varchar(500))
EXTERNAL NAME 'udr!gen_rows'

с объявлением в XE7 [0 .. 4 * 500 - 1] у меня не прокатило.
...
Рейтинг: 0 / 0
Написание UDR
    #39385140
__Avenger__
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
seertrueс объявлением в XE7 [0 .. 4 * 500 - 1] у меня не прокатило.

Delphi XE7
Код: sql
1.
Str: array [0..4*8000 - 1] of AnsiChar;

- полет нормальный.
...
Рейтинг: 0 / 0
Написание UDR
    #39385142
seertrue
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
seertrue
В UDR реально ли ...

Вопрос снимается, сам дурак!
...
Рейтинг: 0 / 0
Написание UDR
    #39385147
seertrue
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А для BLOB есть пример?
...
Рейтинг: 0 / 0
Написание UDR
    #39386120
afgm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
seertrueА для BLOB есть пример?
Вот тоже интересно было бы увидеть обработку блоба в UDR и на Delphi.
Пробовал, как в примерах UDR-триггера на С++, но таки не победил. За неимением времени отложил.
...
Рейтинг: 0 / 0
Написание UDR
    #39386780
seertrue
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Нарыл что-то похожее на пример вот тут http://www.sql.ru/forum/1224694/udr-firebird-rabota-s-blob
Но там крохи инфы.

Все приведенные примеры учат обезьянничать, а не мыслить!

Понять принципы работы без минимального описания очень тяжело.

Господа-разработчики, вы понимаете, что задумка ваша интересная, но мертвая без документации!

Что делают эти строки:
inBlob := Context.getAttachment(Status).openBlob(Status, context.getTransaction(Status), inMsg, 0, nil);
outBlob:= Context.getAttachment(Status).createBlob(Status, context.getTransaction(Status), inMsg, 0, nil);
по упомянутой ссылке?
...
Рейтинг: 0 / 0
Написание UDR
    #39387772
seertrue
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Все, фантазия кончилась.

Задача функции, загрузить файл в BLOB поле.

На входе имя файла на выходе сам файл как BLOB.

Объявляю в базе.
Код: sql
1.
2.
3.
4.
5.
create or alter function LOAD_FILE (
    N1 varchar(255) character set UTF8)
returns blob sub_type 0 segment size 80
EXTERNAL NAME 'Udr!load_file'
ENGINE UDR



Все нормально. Ф-ция есть.

Исходники модуля Delphi XE7
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
unit UdrBlob;

interface

uses
  System.SysUtils, FbApi, System.Classes;

const
  SizeField = 255;
  cMaxBufSize: Word = 16384; //= 8192; //  16384;

type
  TLoadBLOBInMessagePtr = ^TLoadBLOBInMessage;

  TLoadBLOBInMessage = record
    StrLen: Word;
    Str: array [0 .. 4 * SizeField - 1] of AnsiChar;
    StrNull: WordBool;
  end;

  TLoadBLOBOutMessagePtr = ^TLoadBLOBOutMessage;

  TLoadBLOBOutMessage = record
    Size: Word;
    dataB: Blob;
    dataBNull: WordBool;
  end;

  TLoadBLOBFunction = class(ExternalFunctionImpl)
    procedure dispose(); override;
    procedure getCharSet(status: status; context: ExternalContext; name: PAnsiChar;
      nameSize: Cardinal); override;
    procedure execute(status: status; context: ExternalContext; inMsg: Pointer;
      outMsg: Pointer); override;
  end;

  TLoadBLOBFactory = class(UdrFunctionFactoryImpl)
    procedure dispose(); override;
    procedure setup(status: status; context: ExternalContext; metadata: RoutineMetadata;
      inBuilder: MetadataBuilder; outBuilder: MetadataBuilder); override;
    function newItem(status: status; context: ExternalContext; metadata: RoutineMetadata)
      : ExternalFunction; override;
  end;

implementation

uses
  System.AnsiStrings, ib_util;

{TLoadBLOBFunction}

procedure TLoadBLOBFunction.dispose();
begin
  destroy;
end;

procedure TLoadBLOBFunction.getCharSet(status: status; context: ExternalContext; name: PAnsiChar;
  nameSize: Cardinal);
begin
end;

procedure TLoadBLOBFunction.execute(status: status; context: ExternalContext; inMsg: Pointer;
  outMsg: Pointer);
var
  AInMsg: TLoadBLOBInMessagePtr;
  AOutMsg: TLoadBLOBOutMessagePtr;

  //inBlob, outBlob: Blob;

  BufSize, ReadLength, StreamSize: Integer;
  Buffer: PAnsiChar;
  Stream: TStream;

  AFileName: String;
begin
  //пример http://www.sql.ru/forum/1224694/udr-firebird-rabota-s-blob
  try
    AInMsg:=TLoadBLOBInMessagePtr(inMsg);
    AOutMsg:=TLoadBLOBOutMessagePtr(outMsg);

    AFileName:=UTF8ToString(AInMsg.Str);

// что делает эта команда?
    AOutMsg.dataB:=context.getAttachment(status).createBlob(status, context.getTransaction(status),
      outMsg {было inMsg}, 0, nil);

    Stream:=TFileStream.Create(AFileName, fmOpenRead or fmShareDenyNone);
    try
      StreamSize:=Stream.Size; //размер файла
      if StreamSize > cMaxBufSize then //если размер файла больше размера сегмента
        BufSize:=cMaxBufSize//размер под буфер равен размеру сегмента
      else
        BufSize:=StreamSize; //иначе размер под буфер равен размеру файла

      GetMem(Buffer, BufSize); //выделение памяти под сегмент

      try
        while StreamSize <> 0 do begin
          if StreamSize > BufSize then
            ReadLength:=BufSize
          else
            ReadLength:=StreamSize;

          Stream.ReadBuffer(Buffer^, ReadLength);

          AOutMsg.dataB.putSegment(status, ReadLength, Buffer);

          Dec(StreamSize, ReadLength);

        end;
      finally
        FreeMem(Buffer, BufSize);
      end;
    finally
      Stream.Free;
    end;
    AOutMsg.Size:=Stream.Size;
    AOutMsg.dataBNull:=Stream.Size > 0;
  except
    on E: Exception do
      FbException.catchException(status, E);
  end;
end;

{TLoadBLOBFactory}

procedure TLoadBLOBFactory.dispose();
begin
  destroy;
end;

procedure TLoadBLOBFactory.setup(status: status; context: ExternalContext;
  metadata: RoutineMetadata; inBuilder: MetadataBuilder; outBuilder: MetadataBuilder);
begin
end;

function TLoadBLOBFactory.newItem(status: status; context: ExternalContext;
  metadata: RoutineMetadata): ExternalFunction;
begin
  Result:=TLoadBLOBFunction.Create;
end;

end.



пытаюсь выполнить (IBExpert):
Код: sql
1.
2.
3.
select 'D:\tmpFirebird\'||i.name||'.'||i.ext,  load_file('D:\tmpFirebird\'||i.name||'.'||i.ext)
from ins_pict i
where i.id_pict = 3



отрабатывает без ошибок, даже что то выводит, но попытка посмотреть BLOB выдает:

Код: plaintext
1.
2.
3.
4.
5.
6.
Error Message:
----------------------------------------
Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements.
invalid BLOB ID.

[00540F1F] FIB.IBError (Line 539, "FIB.pas" + 55) + $2

Ну естественно попытка записать в поле:
Код: sql
1.
2.
3.
4.
[src]update ins_pict
--from ins_pict i
set pict = load_file('D:\tmpFirebird\'||name||'.'||ext)
where id_pict = 3

[/SRC]

приводит к тому же:
Код: plaintext
1.
Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements.
invalid BLOB ID.

Где ж я накосячил?

Считываемый файл на диске присутствует, в поток загружается...
...
Рейтинг: 0 / 0
Написание UDR
    #39387790
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
seertrue,

Ты путаешь Blob как объект и ISC_QUAD, как id блоба

вот тут
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
  TLoadBLOBOutMessage = record
    Size: Word;
    dataB: Blob;
    dataBNull: WordBool;
  end;
...
// что делает эта команда?
    AOutMsg.dataB:=context.getAttachment(status).createBlob(status, context.getTransaction(status), outMsg {было inMsg}, 0, nil);



по идее должно быть
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
  TLoadBLOBOutMessage = record
    Size: Word;
    dataB: ISC_QUAD;
    dataBNull: WordBool;
  end;
...

var
  outBlob : Blob;
...
// что делает эта команда?
// Блоб создаёт,  а ты что думал ???
    outBlob := context.getAttachment(status).createBlob(status, context.getTransaction(status), AOutMsg.dataB, 0, nil);

...
    AOutMsg.Size := sizeof(ISC_QUAD); // не уверен, что это поле вообще нужно
    AOutMsg.dataBNull := false;
...
Рейтинг: 0 / 0
Написание UDR
    #39387799
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну и конечно не
Код: pascal
1.
AOutMsg.dataB.putSegment(status, ReadLength, Buffer);


а
Код: pascal
1.
outBlob.putSegment(status, ReadLength, Buffer);


и в конце
Код: pascal
1.
outBlob.Release;
...
Рейтинг: 0 / 0
Написание UDR
    #39387802
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
seertrueИсходники модуля Delphi XE7
Потрясающий по глубине нечтения даже той жалкой документации, которая есть, бред.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Написание UDR
    #39387993
seertrue
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry SibiryakovПотрясающий по глубине нечтения даже той жалкой документации, которая есть, бред.


Если это
doc/README.plugins.html
и это
doc/README.external_routines.txt
считается документацией то это я написал "войну и мир"

Спросил тут про документацию:

Симонов Денис:
автордокументации по UDR пока нет, можно в исходниках примеры глянуть. Планирую написать статью, но позже.
Ты попробуй написать, если что не будет получаться спроси здесь, поможем.
...
Рейтинг: 0 / 0
Написание UDR
    #39388005
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Там есть ещё Using_OO_API.html
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Написание UDR
    #39388149
seertrue
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hvlad
по идее должно быть
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
  TLoadBLOBOutMessage = record
    Size: Word;
    dataB: ISC_QUAD;
    dataBNull: WordBool;
  end;
...

var
  outBlob : Blob;
...
// что делает эта команда?
// Блоб создаёт,  а ты что думал ???
    outBlob := context.getAttachment(status).createBlob(status, context.getTransaction(status), AOutMsg.dataB, 0, nil);



может так?
Код: pascal
1.
    outBlob := context.getAttachment(status).createBlob(status, context.getTransaction(status), @AOutMsg.dataB, 0, nil);


CreateBlob просит ISC_QUADPtr
...
Рейтинг: 0 / 0
Написание UDR
    #39388160
seertrue
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hvlad AOutMsg.Size := sizeof(ISC_QUAD); // не уверен, что это поле вообще нужно
[/src]

Нужно! Без него получаю ошибку:
Код: plaintext
1.
Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements.
invalid BLOB ID.
...
Рейтинг: 0 / 0
Написание UDR
    #39388537
seertrue
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry SibiryakovТам есть ещё Using_OO_API.html


Вот я ламер!
Уже читаю...

авторAfter finishing with blob do not forget top close it:

может быть очепятка и надо так?

авторAfter finishing with blob do not forget to close it:
...
Рейтинг: 0 / 0
19 сообщений из 94, страница 4 из 4
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Написание UDR
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]