Yann wrote :
And about params, I don't really understand why binding is made on Recordset data for strings as it's not the case for others types like integer or date and time. So I replaced all "Recordset.GetFieldAs"
in BindAnsiStringFieldValueBufferToSqliteValueAsUTF8
UTF8StrValue := SqlitePassUtils.AnsiToUTF8(PAnsiChar(FieldValueBuffer));
Unfortunately, you shouldn't modify this code because it is also used to bind the values to the update or insert sql statements.
I explain : When a TsqlitePassRecordset record stores a string field, it doesn't directly store a pointer to the string but an integer (index) to a stringlist item. The string itself is stored in the stringlist.
As a consequence, we are dealing here with either a pointer on a string or a stringlist index (integer).
If the stringlist is convenient for debugging, it should be removed now (same for wideString).
I'm going to work on this implementation change.
As a quick fix, you could use :
procedure TSqlitePassParam.BindValue;
var
MasterDataset: TSqlitePassDataset;
begin
if Assigned(FMasterField)
then begin
MasterDataset := TSqlitePassDataset(FMasterField.Dataset);
FValue := MasterDataset.FRecordset.GetFieldValueBuffer(MasterDataset.GetActiveRecord, FMasterField.Tag);
if not MasterDataset.FRecordset.FieldIsNull(FValue)
then FBindValue(FParams.FDataset.FRecordset, FValue, FParams.FDataset.FSQLSelectStmt.StmtHandle, FParamIndex);
end
else if Not FIsNull
then
// Fix
FBindValue(Nil, FValue, FParams.FDataset.FSQLSelectStmt.StmtHandle, FParamIndex);
//
end;
and
procedure BindAnsiStringFieldValueBufferToSqliteValueAsUTF8
(Const Recordset: TSqlitePassRecordset;
Const FieldValueBuffer: PRecBuffer;
Const PreparedStmt: Pointer;
Const PreparedStmtFieldNo: Integer);{$IFDEF HasInline} inline; {$ENDIF}
var
UTF8StrValue: UTF8AnsiString;
begin
// Fix
if Assigned(Recordset)
then UTF8StrValue := SqlitePassUtils.AnsiToUTF8(Recordset.GetFieldAsAnsiString(FieldValueBuffer))
else UTF8StrValue := SqlitePassUtils.AnsiToUTF8(FieldValueBuffer)
//
With Recordset.FDataset.FDatabase
do FEngine.CheckResult(SqliteDbv3_bind_text(PreparedStmt, PreparedStmtFieldNo, pAnsiChar(UTF8StrValue), Length(UTF8StrValue), SQLITE_TRANSIENT));
end;
Thanks for all your testing and your usefull and accurate code analysis.
By the way, I'm looking for fast string sorting with custom collation : the current sort implementation (quicksort derivated) is not too bad but kind of slow with strings comparisons and doesn't handle custom char comparison. I've already looked for a better algo, without any success (RadixSort, PostManSort, String Compression that preserves Chars comparison...etc)
Any idea ?
Best regards.
Luc