#1 2015-05-18 20:25:35

danielkuettner
Member
From: Germany
Registered: 2014-08-06
Posts: 330

case sensitiv delimiter

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

#2 2015-05-18 21:03:50

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,205
Website

Re: case sensitiv delimiter

Do you mean case insensitive?

Offline

#3 2015-05-19 04:17:07

danielkuettner
Member
From: Germany
Registered: 2014-08-06
Posts: 330

Re: case sensitiv delimiter

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

#4 2015-05-19 06:49:12

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,205
Website

Re: case sensitiv delimiter

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

#5 2015-05-19 07:53:27

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,205
Website

Re: case sensitiv delimiter

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

#6 2015-05-19 10:17:16

danielkuettner
Member
From: Germany
Registered: 2014-08-06
Posts: 330

Re: case sensitiv delimiter

My first test was successful.

Thanks,
Daniel

Offline

#7 2015-05-19 12:25:29

danielkuettner
Member
From: Germany
Registered: 2014-08-06
Posts: 330

Re: case sensitiv delimiter

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

#8 2015-05-19 12:42:37

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,205
Website

Re: case sensitiv delimiter

Should be done by http://synopse.info/fossil/info/15abf79914

Thanks for the feedback!

Offline

#9 2015-05-19 12:49:55

danielkuettner
Member
From: Germany
Registered: 2014-08-06
Posts: 330

Re: case sensitiv delimiter

Thanks, AB.

Next error in mORMotDB, function TSQLRestStorageExternal.InternalFieldNameToFieldExternalIndex.

InternalFieldName is 'Gruppe', external is '[Gruppe]', Result is -1 -> raise

Daniel

Offline

#10 2015-05-19 13:48:39

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,205
Website

Re: case sensitiv delimiter

Why is external [Gruppe] ?

Offline

#11 2015-05-19 13:51:42

danielkuettner
Member
From: Germany
Registered: 2014-08-06
Posts: 330

Re: case sensitiv delimiter

Because of MapField?

Offline

#12 2015-05-19 13:52:30

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,205
Website

Re: case sensitiv delimiter

So you mapped your internal field into '[Gruppe]' ?

The code does not support it yet, I'm afraid.

Offline

#13 2015-05-19 14:03:23

danielkuettner
Member
From: Germany
Registered: 2014-08-06
Posts: 330

Re: case sensitiv delimiter

I'm mapping only external fields to [Gruppe].

Offline

#14 2015-05-19 14:27:52

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,205
Website

Re: case sensitiv delimiter

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

#15 2015-05-19 15:19:22

danielkuettner
Member
From: Germany
Registered: 2014-08-06
Posts: 330

Re: case sensitiv delimiter

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

#16 2015-05-19 15:35:41

danielkuettner
Member
From: Germany
Registered: 2014-08-06
Posts: 330

Re: case sensitiv delimiter

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

#17 2015-05-19 15:44:24

danielkuettner
Member
From: Germany
Registered: 2014-08-06
Posts: 330

Re: case sensitiv delimiter

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

#18 2015-05-19 16:05:00

danielkuettner
Member
From: Germany
Registered: 2014-08-06
Posts: 330

Re: case sensitiv delimiter

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

#19 2015-05-20 06:08:36

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,205
Website

Re: case sensitiv delimiter

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

#20 2015-05-20 06:52:58

danielkuettner
Member
From: Germany
Registered: 2014-08-06
Posts: 330

Re: case sensitiv delimiter

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

#21 2015-05-20 07:06:29

danielkuettner
Member
From: Germany
Registered: 2014-08-06
Posts: 330

Re: case sensitiv delimiter

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

#22 2015-05-20 08:04:24

danielkuettner
Member
From: Germany
Registered: 2014-08-06
Posts: 330

Re: case sensitiv delimiter

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

#23 2015-05-20 10:35:37

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,205
Website

Re: case sensitiv delimiter

You may try http://synopse.info/fossil/info/ff05ffb48b

Since the order in fFieldsExternal[] may not match the order in fStoredClassProps.ExternalDB.

Offline

#24 2015-05-20 12:44:04

danielkuettner
Member
From: Germany
Registered: 2014-08-06
Posts: 330

Re: case sensitiv delimiter

Läuft!

Offline

Board footer

Powered by FluxBB