Using RO DA 9.7.115.1441
I’d like to use a different collation in the where conditions with a NewBinaryExpression.
Something like:
WHERE SearchName COLLATE Latin1_general_CI_AI LIKE '%Dlugol%'
How can I do this?
Thanks
Kind regards
Michel
Using RO DA 9.7.115.1441
I’d like to use a different collation in the where conditions with a NewBinaryExpression.
Something like:
WHERE SearchName COLLATE Latin1_general_CI_AI LIKE '%Dlugol%'
How can I do this?
Thanks
Kind regards
Michel
Hi,
I think, you should declare specific macro on server-side and use it like
WHERE {COLLATE(SearchName,Latin1_general_CI_AI)} LIKE '%Dlugol%'
or
WHERE {LATIN_COLLATE(SearchName)} LIKE '%Dlugol%'
your macro should generate
SearchName COLLATE Latin1_general_CI_AI
see TDAMSSQLMacroProcessor.Length
as a example for such macro and TDASQLMacroProcessor.RegisterMacros
for registration of macro.
Thanks for your quick reply.
If I understand correctly I should implement my own macro in uDAADOInterfaces.pas and register it.
Do you have an example for using these macro’s?
Hi,
check the MacroProcessor article.
you should register your macro in default macroprocessor that can be received from default connection like
if Connection.UseMacroProcessor then
if Supports(Connection, IDAHasMacroProcessor, lmacro) then begin
if Assigned(lmacro.GetMacroProcessor) then begin
// register macro here
lmacro.GetMacroProcessor.RegisterProc('COLLATE', MyCollateMethod, 1);
end;
end;
it can be done, say, in the OnAfterAcquireConnection event.
Okay, I tried this I had my doubts about using a macro with the DAWherebuilder… I implemented and registered my Collate function.
I thought I’d replace then fieldname with the macro:
Result := wb.NewBinaryExpression(aDataSource.DataTable.LogicalName, '{Collate('+fld_vw_POSearchName+', '+'Latin1_general_CI_AI)}', dboLike, '%'+ sFilter + '%', datWideString)
But I get an error:
'{Collate(SearchName, Latin1_general_CI_AI)}' field can't be used inside the where clause
I only need the collation on a specific field and the client decides the search action which does not always include the field SearchName.
How can I accomplish this?
Hi,
you can’t use {Collate(xxx)}
as is in DynamicWhere expression.
use NewMacro like
Result := wb.NewBinaryExpression(
aDataSource.DataTable.LogicalName,
wb.NewMacro('Collate',[fld_vw_POSearchName,'Latin1_general_CI_AI']),
dboLike,
'%'+ sFilter + '%',
datWideString);
A thanks. Didn’t noticed the NewMacro functions.
Getting closer…
NewMacro has two overloads, one with a string (the macro name) and one with a string and a array of TDAWhereExpression.
I tried both:
Result := wb.NewBinaryExpression( wb.NewMacro('Collate(SearchName, Latin1_general_CI_AI)'),
dboLike,
'%'+ sFilter + '%',
datWideString
)
xml:
< binaryoperation operator="Like">
< macro name="Collate(SearchName, Latin1_general_CI_AI)"/>
< constant type="WideString" null="0">%brand%</ constant>
< /binaryoperation>
and
Result := wb.NewBinaryExpression( wb.NewMacro('Collate', [
wb.NewField(aDataSource.DataTable.LogicalName, fld_vw_POSearchName),
wb.NewConstant('Latin1_general_CI_AI)')
]),
dboLike,
'%'+ sFilter + '%',
datWideString
)
xml:
< binaryoperation operator="Like">
< macro name="Collate">
< field tablename="vw_PO">SearchName</ field>
< constant type="WideString" null="0">Latin1_general_CI_AI)</ constant>
< /macro>
< constant type="WideString" null="0">%brand%</ constant>
< /binaryoperation>
Both give the same error on the server:
A "safecall" error occured, but the source object did not provide the proper error information. Sorry we cannot be more helpful at this time.
What am I doing wrong?
Hi,
this one works for me:
wb.Expression := wb.NewBinaryExpression(
wb.NewMacro('COLLATE_LATIN', [
wb.NewField(ServerDataModule.tbl_Customers.LogicalName, 'CustomerID')]),
dboLike,
'%'+ Edit1.Text + '%',
datWideString);
VCLApplication.zip (32.7 KB)
Note: ADO driver cannot process correctly COLLATE :param1
so I’ve hardcoded it as COLLATE Latin1_general_CI_AI
.
Thanks,
Your example works fine here. I’ve copy-paste your code. But the exact same macro doesn’t work in our application… I get the same where expression but the server keeps giving the safecall error. If I remove the macro (use the old code) and it works fine, of course without the collation.
I see that the macro is registered in the service.
After that I get a msgBINWriteException:
A "safecall" error occured, but the source object did not provide the proper error information. Sorry we cannot be more helpful at this time.
Any ideas where to look for the problem? Are there special properties I have to set for macro’s?
Hi,
can you create a simple testcase that reproduces that error, pls?
you can drop email to support@ for keeping privacy.
Hello,
I tried to build a testcase but I can’t reproduce the error in a testcase.
I got the macro working in our application but sometimes it gives the safecall error. It has something to do with the acquired connection but I can’t pinpoint it. Running out of time.
I’m going to try to find another solution.
Is it possible to change the generated WHERE condition in the SQL statement on the server?
Thanks
Hi,
yes, it is possible.
you can use IDADataset.OnBeforeOpen
event and check Self.SQL
property
I can’t seem to find where the dataset is on the server.
I have a DataAbstract service with the table in the Schema.
The client has a TDAMemDataTable with the dynamic where. There I find an OnBeforeOpen event.
Where should I implement the OnBeforeOpen to change the SQL property?
Thanks
Hi,
it can be something like
procedure TDataService.DataAbstractServiceBeforeGetDatasetData(aSender: TObject;
const aDataset: IDADataset; const aIncludeSchema: Boolean;
const aMaxRecords: Integer);
begin
if aDataset.LogicalName = myName then
aDataset.OnBeforeOpen := MyBeforeOpen;
end;
Thanks.
I’m sorry but IDADataset does not have a SQL property.
Hi,
Sorry, cast it to IDAServerDataset:
(aDataset as IDAServerDataset).SQL
Yes, it works.
When I have time, I going to try to find out why the macro is not always working.
Thanks you very much.