You are not logged in.
Pages: 1
Is there a way to make mORMot case-sensitiv?
If I use mapfield for externaldb then creation of table is fine, but mORMot then tries to create fields, that was already created before and raise an exception.
Daniel
Offline
No casesensitiv.
For mssql I need a delimiter of [Col], for firebird "Col".
For tablename I can do it with VirtualTableExternalRegister;
but for Tablenames I see no way.
Offline
I'm sorry I do not get it exactly what you expect.
I've added a new itoNoCreateMissingField option to void the creation of missing fields in TSQLRestServerDB.CreateMissingTables.
See http://synopse.info/fossil/info/6972509ea3
It may help to circumvent the issue in the meanwhile.
Offline
OK.
I think I've understood your problem.
I've added the new dedicated TSQLRecordPropertiesMapping.Options settings, e.g. rpmNoCreateMissingTable, rpmNoCreateMissingField or rpmMissingFieldNameCaseSensitive.
It would let TSQLRestStorageExternal.Create behave as you expect, I hope.
See http://synopse.info/fossil/info/73ec73141b
Offline
My first test was successful.
Thanks,
Daniel
Offline
Hi Arnaud,
there is one thing to change in mORMotDB.pas:
in constructor TSQLRestStorageExternal.Create is a local procedure GetFields.
The fTableName is already quoted with VirtualTableExternalRegister ([] or "") and will be quoted twice in SynDBZeos by TSQLDBZeosConnectionProperties.GetFields.
Because of this Zeos can't get metadata for the double-quoted Tablename.
Daniel
Offline
Should be done by http://synopse.info/fossil/info/15abf79914
Thanks for the feedback!
Offline
Thanks, AB.
Next error in mORMotDB, function TSQLRestStorageExternal.InternalFieldNameToFieldExternalIndex.
InternalFieldName is 'Gruppe', external is '[Gruppe]', Result is -1 -> raise
Daniel
Offline
Because of MapField?
Offline
I'm mapping only external fields to [Gruppe].
Offline
Yes, but this is unsupported by the current code base.
Such [] or "" quoting are very DB-specific, and low-level DB libraries do not handle them the same way.
So making a generic support of it may be quite error prone.
Offline
I understand. But CreateMissingTables works very well with your "small" changes.
To use your framework really and to avoid coding all by myself, I need a way to work case-sensitiv. My javascript client is also casesensitiv and the DB-backend could change dependent on client-choices or technical changes in time.
I have to be sure, that tablenames or fieldnames were created as I want it with my TSQLRecords.
Do you see a way to support this? At the moment I've the problem only in TSQLRestBatch.
Daniel
Offline
function TSQLRestStorageExternal.InternalFieldNameToFieldExternalIndex(
const InternalFieldName: RawUTF8): integer;
begin
result := StoredClassRecordProps.Fields.IndexByNameOrExcept(InternalFieldName); <-- this is good; result for 'Gruppe' is 0
result := fFieldsInternalToExternal[result+1]; <-- but here fFieldsInternalToExternal has value of (0, -1, -1, -1, -1, -1, -1, -1, -1, -1) and results in -1
end;
Offline
problem seems to be here:
function TSQLRecordPropertiesMapping.ExternalToInternalIndex(
const ExtFieldName: RawUTF8): integer;
begin
if IdemPropNameU(ExtFieldName,RowIDFieldName) then
result := -1 else begin
// search for customized field mapping
for result := 0 to high(fFieldNames) do
if IdemPropNameU(ExtFieldName,fFieldNames[result]) then <-- fFieldNames[result] is [Gruppe]
exit;
result := -2; // indicates not found
end;
end;
Could you make a fix here like:
if IdemPropNameU(ExtFieldName,Unquote(fFieldNames[result])) then
and unquote removes all suche delimiters ([, ", ...) but only if rpmMissingFieldNameCaseSensitive in TSQLRecordPropertiesMapping.Options?
Daniel
Offline
With this code my TRestBatch works fine:
function TSQLRecordPropertiesMapping.ExternalToInternalIndex(
const ExtFieldName: RawUTF8): integer;
function UnQuotedFieldNames(aFieldName: RawUTF8): RawUTF8;
var
i: Integer;
begin
Result:= '';
for i:= 1 to Length(aFieldName) do
if not (aFieldName[i] in ['[', ']', '"', '''']) then <-- here some other quotes are still missing, I don't know what mysql, postgres ... are using
Result:= Result + aFieldName[i];
end;
begin
if IdemPropNameU(ExtFieldName,RowIDFieldName) then
result := -1 else begin
// search for customized field mapping
for result := 0 to high(fFieldNames) do
if IdemPropNameU(ExtFieldName,UnQuotedFieldNames(fFieldNames[result])) then
exit;
result := -2; // indicates not found
end;
end;
Last edited by danielkuettner (2015-05-19 16:05:57)
Offline
Should be implemented by http://synopse.info/fossil/info/db5c0c622e
But I do not know if it would be sufficient.
What is nice is that it should not break any existing code.
Thanks for the feedback.
Offline
Thanks.
I have to test more, sorry.
My Batch was successful, but only with MSSQL, with FB not. MSSQL accepts Gruppe also without [, in Fb Gruppe <> "Gruppe".
In mORMotDB line 1810 ExternalFields will created only from Fieldnames from JSON ('Gruppe') and fFieldsInternalToExternal array. Here I would need access to Option if CaseSensitiv or the "real" ExternalField-list (with [ or ").
Perhaps second way this is already possible, but I don't know.
Daniel
Offline
There is fFieldNames in Debugger (but I don't the class, instance), here we have the right external Fieldnames (e.g. "Gruppe").
In TSQLRestStorageExternal.InternalBatchStop there is fStorageClassProps with "right" external fieldnames.
Last edited by danielkuettner (2015-05-20 07:13:07)
Offline
So it works also with firebird:
function TSQLRestStorageExternal.JSONDecodedPrepareToSQL(
var Decoder: TJSONObjectDecoder; out ExternalFields: TRawUTF8DynArray;
out Types: TSQLDBFieldTypeArray; Occasion: TSQLOccasion;
BatchOptions: TSQLRestBatchOptions): RawUTF8;
var f,k: Integer;
begin
SetLength(ExternalFields,Decoder.FieldCount);
for f := 0 to Decoder.FieldCount-1 do begin
k := InternalFieldNameToFieldExternalIndex(Decoder.FieldNames[f]);
if k<0 then
raise ESQLDBException.CreateUTF8(
'%.JSONDecodedPrepareToSQL: Unknown field "%" in %',
[self,Decoder.FieldNames[f],StoredClass]);
//fFieldNames
if IsRowID(Pointer(Decoder.FieldNames[f])) then
ExternalFields[f] := fFieldsExternal[k].ColumnName
else
ExternalFields[f] := fStoredClassProps.ExternalDB.FieldNameByIndex(k-1);
Types[f] := fFieldsExternal[k].ColumnType;
end;
This line have to be fixed in the right way:
ExternalFields[f] := fStoredClassProps.ExternalDB.FieldNameByIndex(k-1);
Perhaps you know how?
Offline
You may try http://synopse.info/fossil/info/ff05ffb48b
Since the order in fFieldsExternal[] may not match the order in fStoredClassProps.ExternalDB.
Offline
Läuft!
Offline
Pages: 1