#2 mORMot 1 » problem with TDocVariantData.SearchItemByValue and varOleStr » 2022-10-10 15:21:44

dka1
Replies: 3

Hello AB,
using TDocVariantData.SearchItemByValue with values string (varOleStr)
I get error "Could not convert variant of type (OleStr) into type (Double)"
When debug I see function SortDynArrayVariantComp compare as string "CMP" only when value is type varString, all other values compared as "ICMP"
I change code as bellow and work, but I do not know if it safe (what if value type is any)
Can you check it please?

function SortDynArrayVariantComp(const A,B: TVarData; caseInsensitive: boolean): integer;
 ...
  if (AT<=varNull) or (BT<=varNull) then
    result := ord(AT>varNull)-ord(BT>varNull) else
[ins]  if (AT = varOleStr) or (BT = varOleStr) or (AT = varString) or (BT = varString) then
    result := CMP[caseInsensitive](variant(A),variant(B))
  else
    result := ICMP[VarCompareValue(variant(A),variant(B))][/ins]
[del]{  if (AT<varString) and (BT<varString) then
    result := ICMP[VarCompareValue(variant(A),variant(B))] else
    result := CMP[caseInsensitive](variant(A),variant(B));}[/del]
end;

#3 mORMot 1 » docvariant Return value For Unknown Property » 2022-05-29 05:04:32

dka1
Replies: 1

Hello,
I need a way to check missing properties so I will use "Exists",
but can I implement an option to return "undefined"
(as javascript return for unknown property) ?

TDocVariantOption has dvoReturnNullForUnknownProperty option
that return null for unknown property else raise an EDocVariant.

#4 Re: mORMot 1 » TDocVariant.names raise AV » 2022-05-06 15:11:26

As I wrote at the beginning NamesEx Is my workaround to stop AV

dka1 wrote:

Hello,
I try to replace superobject with TDocVariant (Delphi 7).
I have a problem (access violation) when I try to access Names property eg DocVariantData(mydoc).Names.
If on TDocVariantData add a new property NamesEx and use a function to return VName private variable then it works.

Is I missing something?

#5 Re: mORMot 1 » TDocVariant.names raise AV » 2022-05-06 10:39:30

Synopsis,
bellow code run (on IDE) only if do BUILD not compile

procedure Strange;
var v: variant;
begin
  TDocVariant.New(v);
  v.Code:= '000';
  v.Descr:= 'xxx';
  showmessage(DocVariantData(v)^.NamesEx[0]); //always run <this is my property (that use a function to result:= VName)>
  showmessage(DocVariantData(v)^.Names[0])      //cause AV. Run only after BUILD
end;

#6 Re: mORMot 1 » TDocVariant.names raise AV » 2022-05-06 09:39:15

I did not change syncommons.pas to mark it as rebuild.
With build force IDE to recompile my unit1.pas and also syncommons.pas, SynLZ.pas (this is strange)

#7 Re: mORMot 1 » TDocVariant.names raise AV » 2022-05-06 08:47:07

Ok there are very strange behavior.
1) start delphi 7 IDE that create a new project
2) write this code in TForm1.FormCreate
var v: variant;
begin
  TDocVariant.New(v);
  v.Code:= '000';
  v.Descr:= 'xxx';
  DocVariantData(v).Names[0]:= '222';
3) delete any previous project1.exe
4) compile it and run get AV
5) build and run NOW IS OK
close the IDE, then redo all  starting from step 1 and get the same behavior

#8 Re: mORMot 1 » TDocVariant.names raise AV » 2022-05-06 07:42:48

also it work v.name(0) eg showmessage(v.name(0))
but is read only

#9 Re: mORMot 1 » TDocVariant.names raise AV » 2022-05-06 07:38:39

Thanks for your answerers but my problem exists.
Here a simple code that raise AV
var v: variant;
begin
  TDocVariant.New(v);
  v.Code:= '000';
  v.Descr:= 'xxx';
  DocVariantData(v).Names[0]:= '222';

#10 Re: mORMot 1 » TDocVariant.names raise AV » 2022-05-05 15:02:54

actually DocVariantData(item)^.Names[0]

#11 Re: mORMot 1 » TDocVariant.names raise AV » 2022-05-05 15:00:20

I mean DocVariantData(item).Names[0]

#12 mORMot 1 » TDocVariant.names raise AV » 2022-05-05 08:23:26

dka1
Replies: 16

Hello,
I try to replace superobject with TDocVariant (Delphi 7).
I have a problem (access violation) when I try to access Names property eg DocVariantData(mydoc).Names.
If on TDocVariantData add a new property NamesEx and use a function to return VName private variable then it works.

Is I missing something?

#13 Re: mORMot 1 » SysUtils patch » 2017-08-24 07:51:50

I want to use SysUtils not only for mORMot.
Use of BPL is for runtime loading of features (as plugin's). I will check DLL approach.

Thank you.

#14 Re: mORMot 1 » SynDB/SynOleDB new features » 2017-08-23 11:54:56

you are welcome if you want something more.

#15 mORMot 1 » SysUtils patch » 2017-08-23 11:52:46

dka1
Replies: 2

Hi Arnaud,
I like your SysUtils optimized functions but I compile my app with runtime packages and I think
I must recompile also delphi packages if I use it.
Also what I can do If I have third party components with dcu only?

Do you think Is a good alternative to patch delphi functions with yours?

#16 Re: mORMot 1 » SynDB/SynOleDB new features » 2017-08-21 15:14:34

Hello Arnaud,
I implemented varchar only for OLEDB (synOleDB) driver.
I change synDB   

procedure TSQLDBStatement.ColumnsToBinary
...
  ftAnsiString:
    W.Write(ColumnString(F));
...

and synCommons to add it on type TSQLDBFieldType.
I did because I have many Varchar fields and I want to gain as more space and speed (I use TStringField and TClientDataSet).

About multi result as I wrote I implemented b) in SynOleDB and works.
The requirement is to send one sql batch that include more than one result set.
I use this ms sql feature on SDAC and I need it on synOLEDB (as I intend to abandon SDAC).
An example:

declare @tbl table(id int);
insert into @tbl(id) select id from Customer where name like 'Alpha%' and code like '1__%';
select code,name from customer cus inner join @tbl t on t.id= cus.id;
select trndate, trnAmount from customerTrans cust inner join @tbl t on t.id= cust.CusID;

My implementation is

  ISQLDBStatementMultiResult = interface(ISQLDBStatement)
  ['{A4792685-787C-4DFD-848B-90503AA23EE3}']
    procedure ExecutePreparedMultiResult(out mr: IMultipleResults);
    function GetNextResult(const mr: IMultipleResults): Boolean;    
  end;

  TOleDBStatement = class(TSQLDBStatement, ISQLDBStatementMultiResult)
  ...
    // ISQLDBStatementMultiResult
    procedure ExecutePreparedMultiResult(out mr: IMultipleResults);
    function GetNextResult(const mr: IMultipleResults): Boolean;

  implementation

function TOleDBStatement.GetNextResult(const mr: IMultipleResults): Boolean;
var
  res: HResult;
  RowSet: IRowSet;
begin
  result:= false;
  Reset;
  if mr = nil then
    Exit;
  repeat
    res := mr.GetResult(nil,0,IID_IRowset, @fUpdateCount, @RowSet);
  until Assigned(RowSet) or (res <> S_OK);
  result:= Assigned(RowSet);
  if result then
    FromRowSet(RowSet);
end;

procedure TOleDBStatement.ExecutePreparedMultiResult(out mr: IMultipleResults);
   code here is the same as original procedure ExecutePrepared
   the only difference is that declaration of mr: IMultipleResults is not part of local var but an out param.

I change also procedure ExecutePrepared as

procedure TOleDBStatement.ExecutePrepared;
var
  mr: IMultipleResults;
begin
  ExecutePreparedMultiResult(mr);
end;

Here is how I use it

var
  mr: IMultipleResults;
  stm:  ISQLDBStatementMultiResult;
begin
  stm:= db.NewThreadSafeStatementPrepared(''
           +'declare @tbl table(id int);'
           +'insert into @tbl(id) select id from Customer where name like ''Alpha%'' and code like ''1__%''; '
           +'select code,name from customer cus inner join @tbl t on t.id= cus.id;'
           +'select trndate, trnAmount from customerTrans cust inner join @tbl t on t.id= cust.CusID;'  , True);
  stm:= db.NewThreadSafeStatementPrepared(s, True);
  stm.ExecutePreparedMultiResult(mr);
  while stm.GetNextResult(mr) do
    while stm.Step do
      ShowMessage(stm.ColumnName(0));

Your feedback is welcome.

#17 mORMot 1 » SynDB/SynOleDB new features » 2017-08-11 07:13:33

dka1
Replies: 4

Hello Arnaud,
I need

  1. A datatype ftAnsiString (as varchar) as it faster (no conversion RawUnicodeToUtf8) and has smaller size

  2. The oleDB's multi result feature means get all results (one by one) of a multi select sql statement eg: "select a;select b;select c;"

I implement both a) in SynDB and b) in SynOleDB and works.
Do you want to send the code and add it to your codebase?

#19 Re: mORMot 1 » Can't get result/out parameters from callback interface » 2017-08-03 18:05:02

I run "TestSQL3" tests and I add a breakpoint on procedure TSQLRestClientURI.InternalNotificationMethodExecute
line 36685

 WR.AddShort('{"result":[');

When execution passed there are three methods

ServiceRecordVersionCallback.Deleted
ServiceRecordVersionCallback.Updated
BidirCallback.AsynchEvent

all three methods do not have return or var/out parameters.
I think there is a problem or not supported callback with functions Or var/out parameters.

Please take a look because I try all day and I can't find a solution.
Take as a reference LongWorkServer/client demo and add a callback with functions Or var/out parameters.

#20 Re: mORMot 1 » Can't get result/out parameters from callback interface » 2017-08-03 08:59:38

I change Project31 / LongWorkServer / LongWorkClient and add a callback function with result integer and I get the same error
"missing or invalid value" .
Correction "unexpected parameter" get when call a procedure with out/var parameter
Is callback interfaces supporting functions or var/out parameters?

#21 Re: mORMot 1 » Can't get result/out parameters from callback interface » 2017-08-03 08:36:44

I do not know how to change routing but debugging the app and see that both client/server use
TSQLRestRoutingREST.

Is something that I miss?

#22 mORMot 1 » Can't get result/out parameters from callback interface » 2017-08-03 07:52:07

dka1
Replies: 7

Hello ab,
working with callback interface I tried to return value from a function OR an out param from a procedure.
Both of tries result error failed: unexpected parameter "result"

  ISpotCallBack= interface(IInvokable) 
  ['{F8D9E6D3-F435-4C06-923A-9B7D12BBE2E6}']
    procedure IsOk(a: Integer; out b: Boolean);
    OR
    Function IsOk(a: Integer): Boolean;
  end;

From server's error log

20170803 07263359  ' EXC   EInterfaceFactoryException {"Message":"TInterfacedObjectFakeServer.FakeCall(ISpotCallBack.IsOk) failed: unexpected parameter \"result\""} at 004FC9BF mORMot.RaiseError (32126)  stack trace API 004FC9BF mORMot.RaiseError (32126) 004FCDCF mORMot.InternalProcess (32126) 004FD53D mORMot.TInterfacedObjectFake.FakeCall (32126)

Digging on mORMot client code

procedure TSQLRestClientURI.InternalNotificationMethodExecute
...
      WR.AddShort('{"result":[');
      if frames='[0]' then // call before the first method of the jumbo frame
        Call(callback.Factory.MethodIndexCurrentFrameCallback,frames,nil);
      Call(methodIndex,Ctxt.InBody,WR);
      if ok then begin
        if Ctxt.OutHead='' then begin // <>'' if set via TServiceCustomAnswer
          WR.Add(']','}');
...

found that build a json  {"result":[true]} that is not acceptable on server side code

function TInterfacedObjectFake.FakeCall(var aCall: TFakeCallStack): Int64;
...
        smvBoolean..smvWideString: begin
          Val := GetJSONField(R,R,@wasString,nil,@ValLen);
...

GetJSONField retrun nil

Can you help?

#23 Re: mORMot 1 » TSQLDBStatement / Binary format size » 2017-07-28 10:34:16

Stream size of TSQLDBStatement.FetchAllToBinary for varchar columns is 2x more than what actually is cause of converting string to RawUTF8.
Function TOleDBStatement.BindColumns check the actual type of column (DBTYPE_STR, DBTYPE_BSTR, DBTYPE_WSTR) but use Len := Len*2.
I have not a patch because I don't check code further it is core of oledb.
Do you think fix worth's the effort?

#24 mORMot 1 » TSQLDBStatement / Binary format size » 2017-07-28 08:11:16

dka1
Replies: 2

Hello,
last days studying/testing direct access through OleDB.
It is incredible fast against SDAC on select and faster on insert, update and incredible fast using batch (eg 200 rows) statements.
Also very fast binary serialization (FetchAllToBinary), the only disadvantage is data size of binary serialization when column is varchar serializer use 2bytes as of nvarchar column.
Is it possible and not big effort to change it and use actual column type on serialize/de-serialize?

#25 Re: mORMot 1 » Copy of RowsVariant » 2017-07-27 06:22:13

Thank you,
you are really awesome, very fast, available, approachable, high knowledge.
Delphi community must be very proud with people like you,
I am very happy to cooperate with you smile

#26 mORMot 1 » Copy of RowsVariant » 2017-07-26 15:29:05

dka1
Replies: 2

I try to get result of a query using my function

function GetValues(const sql: string; var ResData: variant): boolean
var
  IRows: ISQLDBRows;
begin
  result:= False;
  IRows:= fProps.Execute(SQL, [], @ResData);
  Result:=Assigned(IRows);
  if result then 
    IRows.Step;
end;

But when IRows goes out of scope ResData has no data to access.
Is any way to use a temp variant and then copy values to ResData or I must iterate through IRows
and copy data to ResData  as TDocVariantData(ResValues).AddValue(IRows.ColumnName(i), IRows.ColumnVariant(i))?

#27 Re: mORMot 1 » AV on TSQLDBProxyStatementRandomAccess.ColumnToVariant » 2017-07-26 07:24:51

Because ColumnToVariant implemented on TSQLDBStatement and not on TSQLDBProxyStatementRandomAccess
so my fix is on function TSQLDBStatement.ColumnToVariant(Col: integer; var Value: Variant): TSQLDBFieldType;
and not on function TSQLDBProxyStatementRandomAccess.ColumnToVariant .

#28 mORMot 1 » AV on TSQLDBProxyStatementRandomAccess.ColumnToVariant » 2017-07-25 17:51:50

dka1
Replies: 3

Hello,
I am a new user of framework (started with  MSSQL OLEDB and HTTP server/services).
Palying around (remote OLEDB throught HTTP) I used TSQLDBProxyStatementRandomAccess
to read ISQLDBRows.FetchAllToBinary results, but I get av on call TSQLDBProxyStatementRandomAccess.ColumnToVariant.
Cause is fConnection=nil so when I change your code

function TSQLDBProxyStatementRandomAccess.ColumnToVariant
...
    {$ifndef UNICODE}
    if Assigned(fConnection) and not fConnection.Properties.VariantStringAsWideString then begin
...

everything is ok.
If it is safe please make the fix.

Board footer

Powered by FluxBB