You are not logged in.
Read the link from my previous post, it answers to all your questions.
MPL/GPL/LGPL Three-License
The framework is licensed under a disjunctive three-license giving you the choice of one of the three following sets of free software/open source licensing terms:
Mozilla Public License, version 1.1 or later;
GNU General Public License, version 2.0 or later;
GNU Lesser General Public License, version 2.1 or later.
This allows the use of our code in as wide a variety of software projects as possible, while still maintaining copy-left on code we wrote. See the full licensing terms.
In SQLiteStudio you can define your own collation (Tools - Open collations editor) and open DB as usual.
For the SYSTEMNOCASE you can try this snippet:
function system_nocase(a, b)
{
a = a.toUpperCase();
b = b.toUpperCase();
return (a < b ? -1 : (a > b ? 1 : 0));
}
What is the minimum supported Delphi version for this? Is it 2009?
libcurl backend supports http2.
ZIP supports AES encryption since version 5.2: https://en.wikipedia.org/wiki/ZIP_(file … Encryption
The word "Asynchronous" is usually abbreviated as async, not asynch: https://i.imgur.com/i4MiMIn.png
It works for me with SynSQLite3Static and sqlite3.dll (both tested only for Win32). I used precompiled dll https://www.sqlite.org/download.html
mORMot 1.18.6192, Delphi 10.3.3 CE, test code:
program SynFTS5Test;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
SynCommons,
SynSQLite3,
SynSQLite3Static,
mORMot,
mORMotSQLite3;
type
TSQLRecordFTS5Trigram = class(TSQLRecordFTS5);
TSQLTextRecord = class(TSQLRecordFTS5Trigram)
protected
FText: RawUTF8;
published
property Text: RawUTF8 read FText write FText;
end;
var
VModel: TSQLModel;
VClient: TSQLRestClientDB;
begin
//sqlite3 := TSQLite3LibraryDynamic.Create;
Writeln(SYNOPSE_FRAMEWORK_FULLVERSION);
try
VModel := TSQLModel.Create([TSQLTextRecord]);
VClient := TSQLRestClientDB.Create(VModel, nil, 'fts5.db3', TSQLRestServerDB);
try
VClient.Server.CreateMissingTables;
// ...
finally
VClient.Free;
VModel.Free;
end;
except
on E: Exception do begin
Writeln(E.ClassName, ': ', E.Message);
end;
end;
Writeln('Press ENTER to exit...');
Readln;
end.
Do you link with sqlite3.dll or with SynSQLite3Static.pas?
mORMot version: 1.18.6171
Test code:
uses
System.SysUtils,
SynCommons,
SynSQLite3Static,
mORMot,
mORMotSQLite3;
type
TSQLTextRecord = class(TSQLRecordFTS5)
protected
FText: RawUTF8;
published
property Text: RawUTF8 read FText write FText;
end;
var
VModel: TSQLModel;
VClient: TSQLRestClientDB;
begin
Writeln(SYNOPSE_FRAMEWORK_FULLVERSION);
try
VModel := TSQLModel.Create([TSQLTextRecord]);
VClient := TSQLRestClientDB.Create(VModel, nil, 'fts5.db3', TSQLRestServerDB);
try
VClient.Server.CreateMissingTables;
// ...
finally
VClient.Free;
VModel.Free;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
rises exception:
ESQLite3Exception: Error SQLITE_ERROR (1) [Step] using 3.33.0 - no such tokenizer: simple, extended_errcode=1
Same code works fine with FTS3 and FTS4.
FTS5 have three built in tokenizers:
- The unicode61 tokenizer, based on the Unicode 6.1 standard. This is the default.
- The ascii tokenizer, which assumes all characters outside of the ASCII codepoint range (0-127) are to be treated as token characters.
- The porter tokenizer, which implements the porter stemming algorithm.
It seems, that default "simple" tokenizer was renamed to "ascii" in FTS5 and it isn't a default anymore.
For some functions, like Trim() the easiest is to create an overload
Yea, it easy, but wait: [DCC Error] SynCommons.pas(24041): E2251 Ambiguous overloaded call to 'Trim'
SynTrim is a good name for this function that will fix all troubles.
We can just use fully qualified names for procedures and functions. for example: `unit1.procedure1`
Your example is not relevant because mORMot 2 uses long units names. In my opinion, using prefixes is preferable.
mormot.core.base.TrimU()
SynTrim()
In this blog-post you wrote:
It is also mandatory that you declare the record as packed.
Otherwise, you may have unexpected access violation issues, since alignement may vary, depending on local setting, and compiler revision.
So, if I will use fixed alignment {$A8} and the same compiler to Save/Load records, can I not use "packed"?
I'm asking because in my simple test it works fine without "packed". Tested on Delphi 10.3.3 (x32/x64).
Documentation says:
- will handle packed records, with binaries (byte, word, integer...) and
string types properties (but not with internal raw pointers, of course)
so is it mean that only packed records supported?
And the same question about RecordSaveJson - does it work with all records or packed only (documentation says nothing)?
Is this topic still about FastMM5?
Embarcadero C++ 10.2 "Tokyo" Compiler and Command-line Tools (Win32 only) direct link:
http://altd.embarcadero.com/download/bc … BCC102.zip (45.2Mb)
The Embarcadero 10.2 Tokyo C++ compiler is a free, Clang-based compiler for 32-bit Windows. The download includes a number of other tools, as well as the Dinkumware STL and headers and import libraries required to build both command-line and GUI Windows applications.
But the DLL idea probably wouldn't work because I have a feeling the graphical code cannot run in anything but the main thread.
You can call functions from the main thread, no matter where they are. So, the dll idea should work.
I wold prefer explicit form: SysUtils.Trim(...)
At first, you should answer the question: what is the "large blob" means in your case? Is it 1k, 100k, 1M, 100M?
After this you can go here: https://www.sqlite.org/intern-v-extern-blob.html and check if your case is "green" (than you can use blobs) or "red" (then use file system).
mpv
Problem with linking sqlite3.obj compiled with modern Free C++ compiler (Clang based) under Win32. At that moment mORMot uses classic compiler from Community Edition which ships with commercial use limitations: https://www.embarcadero.com/free-tools/ccompiler
This errors says that you should continue refactoring SynSQLite3Static.pas if you want to get it work.
Open SynSQLite3Static.pas and add constant prefix:
{$ifdef MSWINDOWS}
{$ifdef CPU64}
{$L sqlite3.o} // compiled with C++ Builder 10.3 Community Edition bcc64
{$else}
{$L sqlite3.obj} // compiled with free Borland C++ Compiler 5.5
const _PREFIX = '_'; // compiled with modern C++ Builder Free compiler (Clang based) <------ add this
{$endif}
{$else}
This will fix name underscore problem and than maybe compilation will be successful.
In your obj file this functions named as _CodecGetReadKey, _CodecGetWriteKey etc. so this is naming convention problem. Maybe there is missing some compiler switches?
Explain, what is not working for you?
Did you try to use this bat file: https://github.com/synopse/mORMot/blob/ … ite3/c.bat
@echo off
attrib -r sqlite3.obj
del sqlite3.obj
rem set bcc=\dev\bccXE7
set bcc=d:\dev\bcc
%bcc%\bin\bcc32 -6 -Oi -O2 -c -d -u- sqlite3.c
attrib +r sqlite3.obj
pause
or take this (for win64) and adopt it for win32.
And now, Delphi (2007, 10.3.2) can't compile this unit because of missing initialization section.
Fix:
initialization
// empty
finalization
if PtrInt(curl.Module)>0 then begin
curl.global_cleanup;
FreeLibrary(curl.Module);
end;
1. Add some missing/renamed constants to the TCurlOption: https://github.com/synopse/mORMot/pull/243
Main issue of this constants is to be able to use modern progress callback function (CURLOPT_XFERINFOFUNCTION) as recommended in documentation https://curl.haxx.se/libcurl/c/CURLOPT_ … CTION.html
2. Let pass libcurl dll name as a parameter: https://github.com/synopse/mORMot/pull/245
I would prefer to use the same library name for Win32 and Win64 versions with my application.
LibCurlInitialize can be refactored with additional variable wich solves the problem. I will create pull request with fix tomorrow.
I'm talking about this function:
function CurlIsAvailable: boolean;
begin
try
if curl.Module=0 then
LibCurlInitialize;
result := PtrInt(curl.Module)>0;
except
result := false;
end;
end;
Now, consider situation when thread A and B calls it at same time (library is not initialized yet).
1. Thread A compares curl.Module with zero and call LibCurlInitialize.
2. Thread A enters into critical section inside LibCurlInitialize and load dll into memory (call LoadLibrary), now curl.Module <> 0
3. Thread A interrupted halfway (no any GetProcAddress called yet) and Thread B start its work
4. Thread B compares curl.Module with zero and return True
5. Thread B try access to the any function (for example, curl.easy_init) and fails with AV!
To fix this bug we need to use temporary variable for library handle instead immediately writing to curl.Module.
curl.Module should be written only at the exit from LibCurlInitialize when initialization is fully complete.
/// low-level libcurl library file name, depending on the running OS
LIBCURL_DLL = {$ifdef Darwin} 'libcurl.dylib' {$else}
{$ifdef Linux} 'libcurl.so' {$else} 'libcurl-x64.dll' {$endif}{$endif};
What about Win32 platform? Is it no longer supported?
Thank you.
This test case fails on version 1.18.5015:
uses
mORMot,
SynCommons;
procedure Test_ArraySorted;
var
VCount: Integer;
VArr, VIntArr: TIntegerDynArray;
VDynArr: TDynArray;
begin
VDynArr.InitSpecific(TypeInfo(TIntegerDynArray), VIntArr, djInteger, @VCount);
SetLength(VArr, 1);
VArr[0] := 1;
VDynArr.AddArray(VArr);
VDynArr.Sort;
Assert(VDynArr.Sorted, 'TDynArray.Sort failed!');
end;
Possible fix (SynCommons.pas):
procedure TDynArray.Sort(aCompare: TDynArraySortCompare);
begin
if Count <= 1 then
fSorted := true // array with 0 or 1 element is always sorted
else
SortRange(0,Count-1,aCompare);
end;
Some example may be found here: Delphi System.Zip patch with ZIP64 and LZMA supports
I make some tests and here is 4 Gb file size limitation, not 2. When mORMot needed to write more then 4 Gb data to output file, LongWord type overflow occurs and file truncated to zero.
It would be better if there was an exception with message that Zip file cannot be more than 4 Gb and Zip64 format is not supported.
Ah, I think it's because resulting file size is > 2Gb. In this case Zip64 format should be used (instead simple Zip format) but mORMot doesn't support it.
What type of errors shows 7zip?
What shows unzip with -t switch?
Calculation EngineLastID (when EngineAddCompute = eacMaxIDEachTime) stopped work in mORMot with MongoDB 3.6 because now mongo require cursor in aggregate requests:
Changed in version 3.6: MongoDB 3.6 removes the use of aggregate command without the cursor option unless the command includes the explain option. Unless you include the explain option, you must specify the cursor option.
To indicate a cursor with the default batch size, specify cursor: {}.
To indicate a cursor with a non-default batch size, use cursor: { batchSize: <num> }.
https://docs.mongodb.com/manual/referen … aggregate/
My pull request with fix: https://github.com/synopse/mORMot/pull/120
Did you test it with 500 or 5000 clients?
I'm not sure exactly, but I think that mORMot can use some Thread poll and the dependence of memory usage on the number of clients will not be linear.
Each Thread use 1 Mb of RAM to its stack, so if mORMot use one Thread per client there is no surprise.
https://msdn.microsoft.com/en-us/librar … s.85).aspx
Ok, now it's work. Thank you!
Yes, it helps.
But here is a new fail:
Assert(not IsMatch('ab[cd]e', 'abdde', False)); // ok
Assert(not IsMatch('ab[cd]ex', 'abddex', False)); // ok
Assert(not IsMatch('ab*.[cd]e', 'ab.dde', False)); // ok
Assert(not IsMatch('ab*.[cd]ex', 'ab.ddex', False)); // fail
Test code:
IsMatch('ab*.[ef]xyz', 'ab.exyz', True);
IsMatch('ab*.[ef]xyz', 'abcd.exyz', True);
IsMatch('ab*.[ef]xyz', 'ab.fxyz', True);
IsMatch('ab*.[ef]xyz', 'abcd.fxyz', True);
all failed!
mORMot version: 1.18.4332.
Compiler: Delphi 2007.
ertank
Bug in this expression in your code: string(KeyPC)
To get Key as a string, use this code:
function GetKey: string;
const
KeyPC: array of Char = [
#00, #101, #02, #03, #40, #05, #106, #07,
#08, #09, #07, #100, #110, #201, #117, #45,
#10, #11, #12, #13, #140, #150, #160, #170,
#13, #1, #17, #130, #40, #16, #106, #70,
#180, #190, #174, #200, #0, #1, #11, #15,
#80, #91, #72, #130, #101, #111, #107, #45
];
var
I: Integer;
begin
SetLength(Result, Length(KeyPC));
for I := 0 to Length(KeyPC) - 1 do begin
Result[I+1] := KeyPC[I];
end;
end;
Fix:
function FastFindInt64Sorted(P: PInt64Array; R: PtrInt; const Value: Int64): PtrInt; overload;
var L: PtrInt;
cmp: Integer;
begin
L := 0;
if 0<=R then
repeat
result := (L + R) shr 1;
{$ifdef CPUX86} // circumvent Int64 comparison slowness
cmp := SortDynArrayInt64(P^[result],Value);
if cmp=0 then
exit else
if cmp<0 then
{$else}
if P^[result]=Value then
exit else
if P^[result]<Value then
{$endif}
L := result + 1 else
R := result - 1;
until (L > R);
result := -1
end;
Test code:
uses
SysUtils,
mORMot,
SynCommons;
procedure DoTest;
var
I, J: Integer;
VLen: Integer;
VArr: TIDDynArray;
begin
VLen := 3;
SetLength(VArr, VLen);
for I := 0 to VLen - 1 do begin
VArr[I] := I;
end;
J := FastFindInt64Sorted(PInt64Array(VArr), VLen-1, 2); // <-- hangs
end;
Previous worked version FastFindInt64Sorted:
function FastFindInt64Sorted(P: PInt64Array; R: PtrInt; const Value: Int64): PtrInt; overload;
var L: PtrInt;
cmp: Int64;
begin
L := 0;
if 0<=R then
repeat
result := (L + R) shr 1;
cmp := P^[result]-Value;
if cmp=0 then
exit;
if cmp<0 then
L := result + 1 else
R := result - 1;
until (L > R);
result := -1
end;
Current, bugged version (infinite loop):
function FastFindInt64Sorted(P: PInt64Array; R: PtrInt; const Value: Int64): PtrInt; overload;
var L: PtrInt;
begin
L := 0;
if 0<=R then
repeat
result := (L + R) shr 1;
{$ifdef CPUX86} // circumvent Int64 comparison slowness
result := SortDynArrayInt64(P^[result],Value);
if result=0 then
exit else
if result <0 then
{$else}
if P^[result]=Value then
exit else
if P^[result]<Value then
{$endif}
L := result + 1 else
R := result - 1;
until (L > R);
result := -1
end;
I use Delphi 10.2 and x86 build for test.
EMartin wrote:Just for curiosity, why not just to use a function for readonly access in https://synopse.info/fossil/info/1ff1e5b5c276dcb5 ?
Indeed: see [6b4cc8c]. Thanks!
And function with 1 line of code should be marked as inline if it's possible.
Option WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY replases WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, but not WINHTTP_ACCESS_TYPE_NO_PROXY!
So, if you want to change behavor when fProxyName is empty, you should use WINHTTP_ACCESS_TYPE_DEFAULT_PROXY for windows version < 8.1:
if (OSVersionInfo.dwMajorVersion>=6) and (OSVersionInfo.dwMinorVersion>=3) then
OpenType := WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY else // Windows 8.1 and newer
OpenType := WINHTTP_ACCESS_TYPE_DEFAULT_PROXY else // Windows 8 and older
OpenType := WINHTTP_ACCESS_TYPE_NAMED_PROXY;
Use this option:
TSynLog.Family.HighResolutionTimeStamp := False;