Skip to content

Commit 4028967

Browse files
author
Arnaud Bouchez
committed
orm: properly support null values in TOrmTable
1 parent ea77696 commit 4028967

File tree

3 files changed

+23
-9
lines changed

3 files changed

+23
-9
lines changed

src/mormot.commit.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
'2.3.9427'
1+
'2.3.9428'

src/orm/mormot.orm.base.pas

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2085,7 +2085,6 @@ TOrmTableFieldType = record
20852085
/// the corresponding index in fQueryTables[]
20862086
TableIndex: integer;
20872087
end;
2088-
20892088
POrmTableFieldType = ^TOrmTableFieldType;
20902089

20912090
{$ifdef NOPOINTEROFFSET}
@@ -2447,7 +2446,8 @@ TOrmTableAbstract = class
24472446
function FieldNames: TRawUtf8DynArray;
24482447
{$ifdef HASINLINE}inline;{$endif}
24492448
/// get the Field content (encoded as UTF-8 text) from a property name
2450-
// - return nil if not found
2449+
// - return nil if not found, or for a JSON null value
2450+
// - may return result^ = #0 for JSON ""
24512451
function FieldValue(const FieldName: RawUtf8; Row: PtrInt): PUtf8Char;
24522452
{$ifdef HASINLINE}inline;{$endif}
24532453
/// sort result Rows, according to a specific field
@@ -2687,6 +2687,7 @@ TOrmTableAbstract = class
26872687
read fFieldCount;
26882688
/// raw access to the data values memory pointers
26892689
// - you should rather use the Get*() methods which can use the length
2690+
// - returns the text value, nil for JSON null, or #0 for JSON ""
26902691
property Results[Offset: PtrInt]: PUtf8Char
26912692
read GetResults write SetResultsSafe;
26922693
/// raw access to the data values UTF-8 length
@@ -8386,7 +8387,7 @@ procedure TOrmTableAbstract.ToDocVariant(out docs: TVariantDynArray; readonly: b
83868387
procedure TOrmTableAbstract.ToDocVariant(out docarray: variant; readonly: boolean);
83878388
var
83888389
Values: TVariantDynArray;
8389-
begin
8390+
begin // warning: do not inline this method
83908391
ToDocVariant(Values, readonly);
83918392
TDocVariantData(docarray).InitArrayFromVariants(Values, JSON_FAST);
83928393
end;
@@ -9010,7 +9011,7 @@ procedure TOrmTableAbstract.GetJsonValues(
90109011
W.AddBinToHexDisplayQuoted(@i64, IDBinarySize);
90119012
end
90129013
else if U = nil then
9013-
W.AddNull
9014+
W.AddNull // from JSON null (a JSON "" has U^=#0)
90149015
else
90159016
case fFieldType[f].ContentDB of
90169017
ftInt64,

src/orm/mormot.orm.core.pas

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5926,7 +5926,7 @@ constructor TOrmTableJson.Create(const aSql: RawUtf8; JsonBuffer: PUtf8Char;
59265926

59275927
constructor TOrmTableJson.Create(const aSql, aJson: RawUtf8);
59285928
var
5929-
len: integer;
5929+
len: PtrInt;
59305930
begin
59315931
len := length(aJson);
59325932
PrivateCopyChanged(pointer(aJson), len, {updatehash=}false);
@@ -5998,6 +5998,7 @@ function TOrmTableJson.ParseAndConvert(Buffer: PUtf8Char; BufferLen: PtrInt): bo
59985998
var
59995999
i, max, resmax, f: PtrInt;
60006000
P: PUtf8Char;
6001+
datavoid: TOrmTableData; // used for all JSON "" values
60016002
info: TGetJsonField;
60026003
begin
60036004
result := false; // error on parsing
@@ -6006,6 +6007,7 @@ function TOrmTableJson.ParseAndConvert(Buffer: PUtf8Char; BufferLen: PtrInt): bo
60066007
(Buffer = nil) then
60076008
exit;
60086009
// go to start of object
6010+
datavoid := TOrmTableData(0);
60096011
{$ifndef NOPOINTEROFFSET}
60106012
fDataStart := Buffer; // before first value, to ensure offset=0 means nil
60116013
{$endif NOPOINTEROFFSET}
@@ -6040,12 +6042,17 @@ function TOrmTableJson.ParseAndConvert(Buffer: PUtf8Char; BufferLen: PtrInt): bo
60406042
IsRowID(info.Value) then
60416043
fFieldIndexID := i;
60426044
end;
6045+
datavoid := TOrmTableData(PtrUInt(info.Value) + PtrUInt(info.ValueLen)
6046+
{$ifndef NOPOINTEROFFSET} - PtrUInt(fDataStart) {$endif}); // ^ = #0
60436047
f := 0;
60446048
for i := fFieldCount to max do
60456049
begin
60466050
// get a field value
60476051
info.GetJsonFieldOrObjectOrArray({handleobjarr=}true, {normbool=}false);
6048-
SetResults(i, info.Value, info.ValueLen);
6052+
if info.Value <> nil then
6053+
SetResults(i, info.Value, info.ValueLen)
6054+
else if info.WasString then // JSON null -> Value=nil
6055+
fData[i] := datavoid; // JSON "" -> Value^=#0, ValueLen=0
60496056
if (info.Json = nil) and
60506057
(i <> max) then
60516058
// failure (GetRowCountNotExpanded should have detected it)
@@ -6098,7 +6105,10 @@ function TOrmTableJson.ParseAndConvert(Buffer: PUtf8Char; BufferLen: PtrInt): bo
60986105
IsRowID(info.Value) then
60996106
fFieldIndexID := f;
61006107
SetResults(f, info.Value, info.ValueLen);
6101-
if P = nil then
6108+
if datavoid = TOrmTableData(0) then
6109+
datavoid := TOrmTableData(PtrUInt(info.Value) + PtrUInt(info.ValueLen)
6110+
{$ifndef NOPOINTEROFFSET} - PtrUInt(fDataStart) {$endif}); // ^ = #0
6111+
if info.Json = nil then
61026112
break;
61036113
end
61046114
else
@@ -6119,7 +6129,10 @@ function TOrmTableJson.ParseAndConvert(Buffer: PUtf8Char; BufferLen: PtrInt): bo
61196129
fData := pointer(fJsonData);
61206130
end;
61216131
info.GetJsonFieldOrObjectOrArray({objarray=}true, {normbool=}false);
6122-
SetResults(max, info.Value, info.ValueLen);
6132+
if info.Value <> nil then
6133+
SetResults(max, info.Value, info.ValueLen)
6134+
else if info.WasString then // JSON null -> Value=nil
6135+
fData[max] := datavoid; // JSON "" -> Value^=#0, ValueLen=0
61236136
if info.Json = nil then
61246137
begin
61256138
// unexpected end

0 commit comments

Comments
 (0)