#1 Re: mORMot 1 » mORMot.pas GetSQLValues » 2021-10-18 21:15:18

fh

That´s OK, and yes, it is very specific. Thank you any way, we will explore TJSONObjectDecoder and the Batch process and try to avoid GetSQLValues.

#2 Re: mORMot 1 » mORMot.pas GetSQLValues » 2021-10-18 14:21:05

fh

Thank you
Nothing is wrong with current methods.
The legacy system only has read access and only allows inserts by sending the sql text to an intermediate service.
That is why we need to generate the sql text.
We will analyze your recommendation.

#3 mORMot 1 » mORMot.pas GetSQLValues » 2021-10-17 18:22:52

fh
Replies: 4

Hello AB,
I found the GetSQLValues function very useful for generating the insert statement necessary to add records to an inherited table.
However, when the table has a blob field, the syntax is different than what is needed, limiting its usefulness.
Based on what I found in mORMot.pas:


    /// return the UTF-8 encoded SQL source to INSERT the values contained
    // in the current published fields of a TSQLRecord child
    // - only simple fields name (i.e. not TSQLRawBlob/TSQLRecordMany) are updated:
    // BLOB fields are ignored (use direct update via dedicated methods instead)
    // - format is '(COL1, COL2) VALUES ('VAL1', 'VAL2')' if some column was ignored
    // (BLOB e.g.)
    // - format is 'VALUES ('VAL1', 'VAL2')' if all columns values are available
    // - is not used by the ORM (do not use prepared statements) - only here
    // for conveniency
    function GetSQLValues: RawUTF8;
   
function TSQLRecord.GetSQLValues: RawUTF8;
var i: integer;
    V: RawUTF8;
    wasString: boolean;
begin
  result := '';
  if self<>nil then
  with RecordProps do
    if SimpleFields=nil then
      exit else begin
    if HasNotSimpleFields then // get 'COL1,COL2': no 'ID,' for INSERT (false below)
      result := SQLTableSimpleFieldsNoRowID; // always <> '*'
    result := result+' VALUES (';
    for i := 0 to length(SimpleFields)-1 do
    with SimpleFields[i] do begin
      GetValueVar(self,true,V,@wasString);
      if wasString then
        V := QuotedStr(V);
      result := result+V+',';
    end;
    result[length(result)] := ')';
  end;
end;

Since the SQLTableSimpleFieldsNoRowID function returns the list of column names, the result is:
'COL1, COL2 VALUES (' VAL1 ',' VAL2 ')' if some column was ignored
which differs from the definition.
For the correct syntax, as the definition of the GetSQLValues function indicates, it is necessary to enclose this list in parentheses:

    if HasNotSimpleFields then // get 'COL1,COL2': no 'ID,' for INSERT (false below)
      result := '(' + SQLTableSimpleFieldsNoRowID + ')'; // always <> '*'

So the function GetSQLValues could be used in all cases
Regards.

#4 Re: mORMot 1 » Master/slave replication with multiple tables » 2016-05-09 22:58:31

fh

We had a similar problem, trying to replicate the master over an empty slave first time.
We solved adding a call to this function at the initialization of the slave server:

function TMyRestServer.RecordVersionSynchronizeSlaveIni(Master: TSQLRest;
         ChunkRowLimit: integer; OnWrite: TOnBatchWrite): integer;
var
  Table: TSQLRecordClass;
  RecordVersionIni,Tvers,Tprev: TRecordVersion;
  field: TSQLPropInfoRTTIRecordVersion;
  tx: integer;
begin
  Result := 1;
  RecordVersionIni := Self.RecordVersionCurrent();
  if RecordVersionIni=0 then
    RecordVersionIni := -1;
  for tx := 0 to Self.Model.TablesMax do begin
    Table := Self.Model.Tables[tx];
    field := Table.RecordProps.RecordVersionField;
    if field<>nil then begin
      Tvers := 0;
      Self.fRecordVersionMax := RecordVersionIni;
      repeat
        Tprev := Tvers;
        Tvers := inherited RecordVersionSynchronizeSlave(Table, Master, ChunkRowLimit, OnWrite);
        if Tvers<0 then begin
          InternalLog('%.RecordVersionSynchronizeSlaveStart(%): REST failure',[self,Table],sllError);
          Result := 0;
          break;
        end;
      until Tprev = Tvers;
    end;
  end;
  Self.fRecordVersionMax := 0;
end;

Regards

#5 Re: Free Pascal Compiler » Add RTTI for interface » 2015-07-16 17:16:48

fh

With pleasure:

procedure TCurlHTTP.InternalSendRequest(const aData: SockString);
begin // see [url]http://curl.haxx.se/libcurl/c/CURLOPT_CUSTOMREQUEST.html[/url]
  // libcurl has dedicated options for GET,HEAD verbs
  if (fIn.Method='') or (fIn.Method='GET') then begin
    curl.easy_setopt(fHandle,coHTTPGet,1);
    if (aData<>'') and (fIn.Method='GET') then begin // e.g. GET with body
      curl.easy_setopt(fHandle,coCustomRequest,pointer(fIn.Method));
      curl.easy_setopt(fHandle,coNoBody,0);
      curl.easy_setopt(fHandle,coUpload,1);
      fIn.Data := aData;
      fIn.DataOffset := 0;
      curl.easy_setopt(fHandle,coInFile,pointer(self));
      curl.easy_setopt(fHandle,coReadFunction,@CurlReadData);
      curl.easy_setopt(fHandle,coInFileSize,length(aData));
    end;
  end else
  if fIn.Method='HEAD' then
    curl.easy_setopt(fHandle,coNoBody,1) else begin
    // handle other HTTP verbs
    curl.easy_setopt(fHandle,coCustomRequest,pointer(fIn.Method));
    if aData='' then begin // e.g. DELETE or LOCK
      curl.easy_setopt(fHandle,coNoBody,1);
      curl.easy_setopt(fHandle,coUpload,0);
    end else begin // e.g. POST or PUT
      curl.easy_setopt(fHandle,coNoBody,0);
      curl.easy_setopt(fHandle,coUpload,1);
      fIn.Data := aData;
      fIn.DataOffset := 0;
      curl.easy_setopt(fHandle,coInFile,pointer(self));
      curl.easy_setopt(fHandle,coReadFunction,@CurlReadData);
      curl.easy_setopt(fHandle,coInFileSize,length(aData));
    end;
    InternalAddHeader('Expect:'); // disable 'Expect: 100 Continue'
  end;
  curl.easy_setopt(fHandle,coWriteFunction,@CurlWriteRawByteString);
  curl.easy_setopt(fHandle,coFile,@fOut.Data);
  curl.easy_setopt(fHandle,coHeaderFunction,@CurlWriteRawByteString);
  curl.easy_setopt(fHandle,coWriteHeader,@fOut.Header);
end;

Regards

#6 Re: Free Pascal Compiler » Add RTTI for interface » 2015-07-15 19:41:13

fh

We developed an application to manage queues of people needing care at a public hospital, for its various services, using mORMot framework and Delphi 7.
Last week we compiled the project done in Delphi 7 in a virtual machine with Xubuntu, FPC 3.1.1 and Lazarus 1.5. The compilation was successful and we have not encountered problems running the program until now. We had to make a small adjustment in the unit SynCrtSock.pas, class TCurlHTTP, function InternalSendRequest, as the GET method to obtain an array of records needs the parameters in the body and curl does not allow it unless the option coCustomRequest is used.
Congratulations on a great job. Regards

#7 Other components » LVCL - SynCommons » 2013-04-27 13:09:27

fh
Replies: 4

This is my 1st post, congratulations for all this job for you and your team,
and thank you for publishing it. Nice to join you.
I'm studying the framework to apply it in a new development.
Concerning LVCL and GUI I got an error trying to compile mysecnotepad example:
SynCommons.pas(18344) Undeclared Identifier: CheckSynchronize
Apparently missing from LVCL\SysUtis.pas
Regards.

Board footer

Powered by FluxBB