Функции pipelined и диманические курсоры

HOME_X
Дата: 06.12.2007 23:59:33
Доброй ночи уважаемые знатоки Oracle !

Oracle 9I
Пытаюсь из динамического курсора вернуть строки через функцию pipelined
и тип AnyDataSet
Функция в целом работает (если возвращать другой тип, скажем Integer)
Но с диррективой pipe row(RowSave) - дает ошибку
Error: PLS-00801: внутр.ошибка [74303]
Подскажите кто-чем может !

Заранее благодарен и признателен !

create or replace function SqlView(iText in String:=Null) return /*Integer*/ AnyDataSet pipelined
as
  type tRowRead is record
     (Chr_Column   Varchar2(32767),
      Num_Column   Number,
      Date_Column  Date,
      Clob_Column  Clob,
      Raw_Column   Raw(32767),
      Raw_Error    Number,
      Raw_Length   Integer,
      Ids_Column   Interval Day To Second,
      Iym_Column   Interval Year To Month,
      Ts_Column    TimeStamp,
      Tstz_Column  TimeStamp with time zone,
      Tsltz_Column TimeStamp with local time zone,
      Cvl_Offset   Integer:=0,
      Cvl_Length   Integer
     );
  I      Integer;
  SqlExe Integer;
  DbType Integer;
  Fields AnyType;
  RowRead tRowRead;
  RowSave AnyDataSet;
  Describe Dbms_Sql.Desc_Tab2;
begin
  SqlExe:=Dbms_Sql.Open_Cursor;
  Dbms_Sql.Parse(SqlExe,iText,Dbms_Sql.Native);
  Dbms_Sql.Describe_Columns2(SqlExe,I,Describe);
  AnyType.BeginCreate(Dbms_Types.TypeCode_Object,Fields);
  For I in Describe.First .. Describe.Last loop
    Case when Describe(I).Col_Type in(1,96,11,208) then 
              Dbms_Sql.Define_Column(SqlExe,I,'',32767);
              DbType:=Dbms_Types.TypeCode_Varchar2;
         when Describe(I).Col_Type=  2             then 
              Dbms_Sql.Define_Column(SqlExe,I,To_Number(Null));
              DbType:=Dbms_Types.TypeCode_Number;
         when Describe(I).Col_Type=  8             then 
              Dbms_Sql.Define_Column_Long(SqlExe,I);
              DbType:=Dbms_Types.TypeCode_Clob;
         when Describe(I).Col_Type=112             then 
              Dbms_Sql.Define_Column(SqlExe,I,To_Clob(Null));
              DbType:=Dbms_Types.TypeCode_Clob;
         when Describe(I).Col_Type= 12             then 
              Dbms_Sql.Define_Column(SqlExe,I,To_Date(Null));
              DbType:=Dbms_Types.TypeCode_Date;
         when Describe(I).Col_Type= 23             then 
              Dbms_Sql.Define_Column_Raw(SqlExe,I,To_Raw(Null),Describe(I).Col_Max_Len);
              DbType:=Dbms_Types.TypeCode_Raw;
         when Describe(I).Col_Type=180             then 
              Dbms_Sql.Define_Column(SqlExe,I,To_TimeStamp(Null));
              DbType:=Dbms_Types.TypeCode_TimeStamp;
         when Describe(I).Col_Type=181             then 
              Dbms_Sql.Define_Column(SqlExe,I,To_TimeStamp_Tz(Null));
              DbType:=Dbms_Types.TypeCode_TimeStamp_Tz;                
         when Describe(I).Col_Type=231             then 
              Dbms_Sql.Define_Column(SqlExe,I,To_TimeStamp_Tz(Null));
              DbType:=Dbms_Types.TypeCode_TimeStamp_Ltz;
         when Describe(I).Col_Type=182             then 
              Dbms_Sql.Define_Column(SqlExe,I,To_YmInterval(Null));
              DbType:=Dbms_Types.TypeCode_Interval_Ym;  
         when Describe(I).Col_Type=183             then 
              Dbms_Sql.Define_Column(SqlExe,I,To_DsInterval(Null));
              DbType:=Dbms_Types.TypeCode_Interval_Ds;
    End case;
    Fields.AddAttr(Describe(I).Col_Name,DbType,Describe(I).Col_Precision,Describe(I).Col_Scale,
                   Case when Describe(I).Col_Type=11 then 32 else Describe(I).Col_Max_Len End,
                   Describe(I).Col_Charsetid,Describe(I).Col_CharSetForm);
  End loop;
  Fields.EndCreate;
  I:=Dbms_Sql.Execute(SqlExe);
  While Dbms_Sql.Fetch_Rows(SqlExe)>0 Loop
    AnyDataSet.BeginCreate(Dbms_Types.TypeCode_Object,Fields,RowSave);
    RowSave.AddInstance();
    RowSave.PieceWise();
    For I in Describe.First .. Describe.Last loop
      Case when Describe(I).Col_Type in(1,96,11,208) then 
                Dbms_Sql.Column_Value(SqlExe,I,RowRead.Chr_Column);
                RowSave.SetVarchar2(RowRead.Chr_Column);
           when Describe(I).Col_Type=  2             then 
                Dbms_Sql.Column_Value(SqlExe,I,RowRead.Num_Column);
                RowSave.SetNumber(RowRead.Num_Column);
           when Describe(I).Col_Type=  8             then 
                Loop
                  Dbms_Sql.Column_Value_Long(SqlExe,I,32767,RowRead.Cvl_Offset,RowRead.Chr_Column,RowRead.Cvl_Length);
                  RowRead.Clob_Column:=RowRead.Clob_Column||RowRead.Chr_Column;
                  RowRead.Cvl_Offset:=RowRead.Cvl_Offset+32767;
                  exit when RowRead.Cvl_Length<32767;
                End loop;
                RowSave.SetClob(RowRead.Clob_Column);
           when Describe(I).Col_Type=112             then 
                Dbms_Sql.Column_Value(SqlExe,I,RowRead.Clob_Column);
                RowSave.SetClob(RowRead.Clob_Column);
           when Describe(I).Col_Type= 12             then 
                Dbms_Sql.Column_Value(SqlExe,I,RowRead.Date_Column);
                RowSave.SetDate(RowRead.Date_Column);
           when Describe(I).Col_Type= 23             then 
                Dbms_Sql.Column_Value_Raw(SqlExe,I,RowRead.Raw_Column,RowRead.Raw_Error,RowRead.Raw_Length);
                RowSave.SetRaw(RowRead.Raw_Column);
           when Describe(I).Col_Type=180             then 
                Dbms_Sql.Column_Value(SqlExe,I,RowRead.Ts_Column);
                RowSave.SetTimeStamp(RowRead.Ts_Column);
           when Describe(I).Col_Type=181             then 
                Dbms_Sql.Column_Value(SqlExe,I,RowRead.Tstz_Column);
                RowSave.SetTimeStampTz(RowRead.Tstz_Column);
           when Describe(I).Col_Type=231             then 
                Dbms_Sql.Column_Value(SqlExe,I,RowRead.Tsltz_Column);
                RowSave.SetTimeStampLTz(RowRead.Tsltz_Column);
           when Describe(I).Col_Type=182             then 
                Dbms_Sql.Column_Value(SqlExe,I,RowRead.Iym_Column);
                RowSave.SetIntervalYM(RowRead.Iym_Column);
           when Describe(I).Col_Type=183             then 
                Dbms_Sql.Column_Value(SqlExe,I,RowRead.Ids_Column);
                RowSave.SetIntervalDs(RowRead.Ids_Column);
      End case;
    End Loop;
    RowSave.EndCreate();
    pipe row (RowSave);
  End Loop;
  Dbms_Sql.Close_Cursor(SqlExe);
  dbms_output.put_line('Quit');
  return /*Describe.Last*/;
end SqlView;
HOME_X
Дата: 07.12.2007 00:50:13
Табличный тип тоже описывал .......... все равно ругаеться !!!!????

create or replace type TAnyDataSet as table of AnyDataSet
.....
create or replace function SqlView(iText in String:=Null) return /*Integer*/ TAnyDataSet pipelined
.....
SY
Дата: 07.12.2007 03:31:00
HOME_X
Табличный тип тоже описывал .......... все равно ругаеться !!!!????

create or replace type TAnyDataSet as table of AnyDataSet
.....
create or replace function SqlView(iText in String:=Null) return /*Integer*/ TAnyDataSet pipelined
.....


Works in 10.2.0.1.0. However, keep in mind SQL can not process ANYDATASET. All SQL will display is:

SQL> select * from table(SqlView('select * from emp'));

COLUMN_VALUE()
--------------------------------------------------------------------------------
ANYDATASET()
ANYDATASET()
ANYDATASET()
ANYDATASET()
ANYDATASET()
ANYDATASET()
ANYDATASET()
ANYDATASET()
ANYDATASET()
ANYDATASET()
ANYDATASET()

COLUMN_VALUE()
--------------------------------------------------------------------------------
ANYDATASET()
ANYDATASET()
ANYDATASET()

14 rows selected.

SQL> 

SY.
Вячеслав Любомудров
Дата: 07.12.2007 03:49:04
9.2.0.7 -- полет нормальный
tst> sho user
USER is "U1"
tst> create or replace type TAnyDataSet as table of AnyDataSet;
  2  /

Type created.

tst> create or replace function SqlView(iText in String:=Null) return /*Integer*/ TAnyDataSet pipelined
  2  as
...
123  end SqlView;
124  /

Function created.

tst> set serveroutput on
tst> select * from table(SqlView('select * from dual'));

COLUMN_VALUE()
--------------------------------------------------------------------
ANYDATASET()

tst> exec null
Quit

PL/SQL procedure successfully completed.

tst> select * from v$version where rownum=1;

BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.7.0 - Production
HOME_X
Дата: 07.12.2007 08:20:24
SY

............ keep in mind SQL can not process ANYDATASET
SY.


Доброе утро уважаемый SY !
Вы правы - все работает, в коммандном окне запустить не догадался ....

Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production

select * from Table(SqlView('select * from RR12'));

COLUMN_VALUE
------------
<Object>
<Object>
HOME_X
Дата: 07.12.2007 08:27:46
Вячеслав Любомудров

9.2.0.7 -- полет нормальный


Доброе время суток Вячеслав Любомудров !
Простите, а "научить" базу корректно визуализировать обьект шансы есть ?
(SQL окном - ошибка OCI-21500)
Timm
Дата: 07.12.2007 12:41:20
SQL>show err
Errors for FUNCTION SQLVIEW:

LINE/COL ERROR
-------- -----------------------------------------------------------------
1/10     PLS-00630: pipelined functions must have a supported collection
         return type

SQL>disc
Disconnected from Oracle Database 11g Enterprise Edition Release 11.1.0.6.0
HOME_X
Дата: 07.12.2007 14:20:26
Timm
SQL>show err
Errors for FUNCTION SQLVIEW:

LINE/COL ERROR
-------- -----------------------------------------------------------------
1/10     PLS-00630: pipelined functions must have a supported collection
         return type

SQL>disc
Disconnected from Oracle Database 11g Enterprise Edition Release 11.1.0.6.0


Добрый день уважаемый Timm !
Простите не понял Вас .....
Если Вам необходимо классическое решение для Вашей версии могу посоветовать
вариант сам господин великий Oracle его использует ............ прекрасно работает

Но у меня 9I (и изменить версию не в моих силах - не админ базы, пользователь-любитель)
и приходиться извращаться.
Сама функция работает,но как заметил SY - SQL не может классифицировать типы
полей .... и можно ли это обойти ...???? Наверное нет !

Уважаемый Вячеслав Любомудров - у Вас аналогичная версия может посоветуете ?
Вячеслав Любомудров
Дата: 10.12.2007 05:03:45
Давай ты сначала расскажешь, что ты хочешь получить
Нечто универсальное на практике всегда заканчивается гиморроем
Я не работал с таким типом, и, надеюсь, никогда не буду работать. Ибо нехуй
HOME_X
Дата: 10.12.2007 15:08:50
Вячеслав Любомудров

.....................заканчивается гиморроем



Бодрого дня уважаемый Вячеслав Любомудров!
Должен заметить что в ГЛУБИНЕ ГЛУБИН целяком согласен с замечанием !
Особенно если это профессионально реализовано в более высокой версии
и она закуплена и ее УЖЕ полгода не могут поставить !!!!!!!!!!!!???????????

Суть процесса это динамический курсор и возврат значений через Pipelined
функцию. Последную редакцию функции могу приложить, но она мало отли-
чаеться от ранее приведенной.
Насколько понимаю ГЛУБИНУ ГЛУБИН - проблема в том, что функции интер-
фейса OCI не могут развернуть и визуализировать тип AnyDataSet.......!!!!!
Нашел похожую тему с участием господина SY, но там приведена разборка типа на уровне пользователя и
по каждому полю (а если число полей неизвестно ?).
А можно ли научить OCI делать это самостоятельно, без ЯВНОГО вмешательст
ва пользователя ?

Зараннее благодарен за участие !!!!!!!!!