Page 1 of 1

Unicode solution in OraObject?

Posted: Thu 12 Jul 2007 05:55
by helppass
Is there any way to read/write unicode string in OraObject?
****
I am using Delphi 7 and ODAC 5.70.028/6.00.0.6 on Windows XP and Oracle 10g eXpress(international).
****

1. seems "TOraObject.AttrAsString[xxx]" cannot return the true results.
setting of orasession:

Code: Select all

  AOraSession.Options.Charset := 'AL32UTF8';
  AOraSession.Options.UseUnicode := True;
but it is useless..

2. and when reading string by TCLOB.AsWideString, it also returns ansi result when TCLOB is in a returned TOraObject from stored procedure

Code: Select all

  With AOraObject Do
   Begin
    Refresh;
    If Not AttrIsNull['FAQ_ID'] Then
     ABO.FAQ_ID := AttrAsInteger['FAQ_ID'];
    If Not AttrIsNull['FAQ_CATA_ID'] Then
     ABO.FAQ_CATA_ID := AttrAsInteger['FAQ_CATA_ID'];
    If Not AttrIsNull['FAQ_CATA_NAME'] Then
     ABO.FAQ_CATA_NAME := AttrAsString['FAQ_CATA_NAME'];
    If Not AttrIsNull['Q'] Then
     ABO.Q := AttrAsString['Q'];
    If Not AttrIsNull['A'] Then
     s := '';
     Try
      a_ := AttrAsLob['A'].LengthLob;
      If a_ > 0 Then
       Begin
        AttrAsLob['A'].ReadLob;
        s := AttrAsLob['A'].AsWideString;
       End;
     Except
     End;
     ABO.A := s;
    If Not AttrIsNull['OP_ID'] Then
     ABO.OP_ID := AttrAsString['OP_ID'];
    If Not AttrIsNull['STATE'] Then
     ABO.STATE := AttrAsString['STATE'];
    If Not AttrIsNull['CREATE_DATE'] Then
     ABO.CREATE_DATE := AttrAsDateTime['CREATE_DATE'];
    If Not AttrIsNull['STATE_DATE'] Then
     ABO.STATE_DATE := AttrAsDateTime['STATE_DATE'];
   End;
when I trace into my procedure, I found the property "IsUnicode" of CLOB in the OraObject(which returned from the stored procedure) always be FALSE, how can I solve this problem? (database is encoding as UTF8.)

I got ansi results when read data to a pointer, :cry:
accessing such a clob in jdbc returns the unicode results :(

3. call .refresh method of an OraArray in a complex OraObject returned from stored procedure always cause a "EAccessVoilation in Adress .... in orageneric9.dll".

here is A FULL SAMPLE below:

Code: Select all

  With AOraObject Do
   Begin
    Refresh;
    If Not AttrIsNull['FAQ_ID'] Then
     ABO.FAQ_ID := AttrAsInteger['FAQ_ID'];
    If Not AttrIsNull['FAQ_CATA_ID'] Then
     ABO.FAQ_CATA_ID := AttrAsInteger['FAQ_CATA_ID'];
    If Not AttrIsNull['Content'] Then
     ABO.Content := AttrAsString['Content'];
    If Not AttrIsNull['BeginDate'] Then
     ABO.BeginDate := AttrAsDateTime['BeginDate'];
    If Not AttrIsNull['EndDate'] Then
     ABO.EndDate := AttrAsDateTime['EndDate'];
    If Not AttrIsNull['Faq'] Then
      Begin
       Try
        AttrAsArray['Faq'].Refresh;  //  Nil Then
       TAdsOraEx.SaveToOraObject(AOraSession, ABO.Ads[b_], AttrAsArray['Ads'].ItemAsObject[b_]);
     End;
    // キオサリオトケ羣・save accomplished.
   End;

  Result := AOraObject;
 End;
when calling:

Code: Select all

 PROCEDURE SPLASHADS(vo_SplashAds IN OUT BT_SPLASHADS, vo_OperationStatus OUT NUMBER, vo_OperationStatusDesc OUT VARCHAR2) AS
	 --ソ?ヒルキオサリミ靨ェオトケ羣?
	 PRC_NAME CONSTANT VARCHAR2(50) := 'SPLASHADS';

	 step NUMBER;

	BEGIN

	 step := 1;
	 -- begin to work -----------------

   SELECT BT_ADS(
                 ADS_ID,
                 ADS_TIP,
                 ADS_IMG,
                 ADS_WIDTH,
                 ADS_HEIGHT,
                 ADS_URL,
                 ADS_TYPE,
                 ADS_KEYWORDS,
                 CREATE_DATE,
                 OP_ID,
                 STATE,
                 STATE_DATE
                )
     BULK COLLECT
     INTO vo_SplashAds.ADS
     FROM (
                   SELECT ADS_ID,
                          ADS_TIP,
                          ADS_IMG,
                          ADS_WIDTH,
                          ADS_HEIGHT,
                          ADS_URL,
                          ADS_TYPE,
                          ADS_KEYWORDS,
                          STATE,
                          CREATE_DATE,
                          OP_ID,
                          STATE_DATE
                     FROM ADS
                    WHERE (vo_SplashAds.ADS_TYPE IS NULL OR ADS.ADS_TYPE = vo_SplashAds.ADS_TYPE)
                      AND (vo_SplashAds.ADS_WIDTH = ADS.ADS_WIDTH)
                      AND (vo_SplashAds.ADS_HEIGHT = ADS.ADS_HEIGHT)
                    ORDER BY dbms_random.value
          )
    WHERE ROWNUM  Nil Then
       TGoodsCataOraEx.SaveToOraObject(AOraSession, ABO.GoodsCata[b_], AttrAsArray['GoodsCata'].ItemAsObject[b_]);
     End;
    // カッサュキヨタ・save accomplished.
   End;

  Result := AOraObject;
 End;

Procedure TAutoService.Ora_ListGoodsCata(var AOraEx: TListGoodsCata);
 Var
  AOraQuery: TSmartQuery;
  AOraObject: TOraObject;
 Begin
  If Not AOraSession.Connected Then AOraSession.Connect;
  AOraQuery := TSmartQuery.Create(Nil);
  AOraQuery.Session := AOraSession;

  Try
   AOraQuery.SQL.Text := 'BEGIN ControlPanel.LISTGOODSCATA(:BO, :OperationStatus, :OperationStatusDesc); END;';
   AOraObject := TListGoodsCataOraEx.SaveToOraObject(AOraSession, AOraEx);
   AOraQuery.ParamByName('BO').AsObject := AOraObject;
   AOraQuery.ParamByName('OperationStatus').AsInteger := 0;
   AOraQuery.ParamByName('OperationStatusDesc').AsString := '';
   AOraQuery.Execute;

   AOraObject := AOraQuery.ParamByName('BO').AsObject;
   TListGoodsCataOraEx.LoadFromOraObject(AOraObject, AOraEx);
   AOraEx.OperationStatus := AOraQuery.ParamByName('OperationStatus').AsInteger;
   AOraEx.OperationStatusDesc := AOraQuery.ParamByName('OperationStatusDesc').AsString;
  Except
   On E: Exception Do
    Begin
     AOraEx.OperationStatus := 21909;
     AOraEx.OperationStatusDesc := 'WOA Error:' + E.Message;
    End;
  End;

  If AOraQuery.Active Then AOraQuery.Close;
  Try
   AOraObject.Free;
  Except
  End;
  AOraQuery.Free;
 End;

:arrow: SmartQuery.ParamByName.AsObject.AttrAsArray.Refesh raise exception... :cry:

Posted: Fri 13 Jul 2007 10:57
by Plash
1. ODAC does not support Unicode in objects.
2. You should call the Refresh method only for top level objects. This probably refreshes all inner objects. This is an OCI limitation.
I think there is no need to call the Refresh method for object returned by stored procedure because they cannot be changed on the server. This method may be used for objects returned by a SELECT statement.

Posted: Wed 18 Jul 2007 08:42
by helppass
Thanks very much for Plash's reply!!

========================

2. in my testing, if I refresh the top level object only, I won't get data that returned from object's subarray, (length === 0).

========================

OK, it means I have to use a java solution to get unicode result instead of ODAC? ...

Although my java solution is ready now, I still strongly want a delphi solution :oops: .... What a pity >_<!!

I hope that I can build a light binary SP2Service under 1M bytes.
JDK,..AAAAAAAAAAAAAAAAA--- :(

Posted: Wed 18 Jul 2007 13:44
by Plash
We have fixed the problem with the Size property returning 0. This fix will be included in the next ODAC build. Anyway you don't need to call the Refresh method for an object returned from a stored procedure.

Yes, Java can be used to read and write Unicode to Oracle objects.