![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Решил я по совету использовать курсоры, чтобы вернуть результат нескольких запросов в одном резалтсете. Ну то есть решить проблему 1+N запросов.
Сделал такой примерчик
ссылко1
ссылко2, скрипт
По идее, на каждую строку результсета должен вернутся открытый курсор, то бишь, мы фетчим внешний резалтсет, а внутри цикла фетча пытаемся фетчить полученный курсор.
На данный момент пока хрен что у меня получается, т.к. все компоненты доступа(и в дельфи, и в дотнете) возвращают первое поле запроса результат запроса "select * from myfunc() as test(a refcursor,b varchar(40))" видят тупо как строку и ни с какого бока к этому курсору не подступится.
Синтаксис работы с курсорами и возвращения множеств из функций postgresql тоже в некотором роде печалит, но это следствие видимо того, что я привык в этому плане к аккуратному синтаксису Firebird.
PS: Кстати, что забавно: в примерах везде приведены только самые простые случаи типа "возвращаем один курсор, возвращаем два заведомо известных курсора", а вот комбинацию "возвращаем множество туплов из курсора и атомарного типа" пришлось придумывать самому, с извращениями в виде create type.
PPS: Гамон. Победил эту хрень. исправленный скрипт (отличия - именование курсора и убрано его закрытие)
1)курсоры нужно именовать уникально, типа
cur='returnedcursor' || cast(parentid as varchar);
2)курсоры не нужно закрывать, т.к. второй запрос выполняется только после того как целиком выполнится первый, а не внутри него, как хотелось бы.
3)возвращенное в первом запросе имя курсора нужно использовать, чтобы обратится к его результатам:
Delphi: 'fetch all from '+q.Fields[0].AsString;
.NET: cmd2.CommandText = "FETCH ALL FROM "+reader1.GetString(0);
4)в дотнете это работает только с PreloadReader=true, иначе ругается что "уже открыт DataReader", я про это уже писал, что только Firebird умеет открывать более одного ридера.
В общем, те же яйца, вид в профиль.
Не знаю, как насчет парсинга запроса и кэширования результата парсинга, запросто может быть, что оно каждый раз во внутреннем цикле это делает повторно, то бишь опять та же проблема 1+N, только стоя и в гамаке.
Кроме того, сразу видно, что PL/pgSQL это ад, т.к. присваивая переменной курсора имя, мы делаем это имя до закрытия курсора доступным в FETCH ALL FROM, то есть, явное смешение данных и метаданных. Это можно было бы считать метапрограммированием, но это больше похоже на динамическую типизацию(анафема!!).
Сделал такой примерчик
ссылко1
ссылко2, скрипт
По идее, на каждую строку результсета должен вернутся открытый курсор, то бишь, мы фетчим внешний резалтсет, а внутри цикла фетча пытаемся фетчить полученный курсор.
На данный момент пока хрен что у меня получается, т.к. все компоненты доступа(и в дельфи, и в дотнете) возвращают первое поле запроса результат запроса "select * from myfunc() as test(a refcursor,b varchar(40))" видят тупо как строку и ни с какого бока к этому курсору не подступится.
Синтаксис работы с курсорами и возвращения множеств из функций postgresql тоже в некотором роде печалит, но это следствие видимо того, что я привык в этому плане к аккуратному синтаксису Firebird.
PS: Кстати, что забавно: в примерах везде приведены только самые простые случаи типа "возвращаем один курсор, возвращаем два заведомо известных курсора", а вот комбинацию "возвращаем множество туплов из курсора и атомарного типа" пришлось придумывать самому, с извращениями в виде create type.
PPS: Гамон. Победил эту хрень. исправленный скрипт (отличия - именование курсора и убрано его закрытие)
1)курсоры нужно именовать уникально, типа
cur='returnedcursor' || cast(parentid as varchar);
2)курсоры не нужно закрывать, т.к. второй запрос выполняется только после того как целиком выполнится первый, а не внутри него, как хотелось бы.
3)возвращенное в первом запросе имя курсора нужно использовать, чтобы обратится к его результатам:
Delphi: 'fetch all from '+q.Fields[0].AsString;
.NET: cmd2.CommandText = "FETCH ALL FROM "+reader1.GetString(0);
4)в дотнете это работает только с PreloadReader=true, иначе ругается что "уже открыт DataReader", я про это уже писал, что только Firebird умеет открывать более одного ридера.
В общем, те же яйца, вид в профиль.
Не знаю, как насчет парсинга запроса и кэширования результата парсинга, запросто может быть, что оно каждый раз во внутреннем цикле это делает повторно, то бишь опять та же проблема 1+N, только стоя и в гамаке.
Кроме того, сразу видно, что PL/pgSQL это ад, т.к. присваивая переменной курсора имя, мы делаем это имя до закрытия курсора доступным в FETCH ALL FROM, то есть, явное смешение данных и метаданных. Это можно было бы считать метапрограммированием, но это больше похоже на динамическую типизацию(анафема!!).