Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | {1536} fixed sftDateTime field recognition from ISO-8601 text |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
afa9f26e47bc2a43b611e08b226fc6ee |
User & Date: | ab 2015-06-23 14:39:48 |
2015-06-23
| ||
14:52 | {1537} DDD allows mapping with a RawUTF8 ORM field for T*ObjArray published fields - in addition to default variant type, if the on-the-fly conversion to/from TDocVariant appears to be a bottleneck check-in: 898b225dab user: ab tags: trunk | |
14:39 | {1536} fixed sftDateTime field recognition from ISO-8601 text check-in: afa9f26e47 user: ab tags: trunk | |
13:50 | {1535} removed the VMT BeforeDestruction trick for T*AutoCreate classes - back to a classic overriden destructor, as expected by any inherited Destroy check-in: d5505e83b7 user: ab tags: trunk | |
Changes to SQLite3/mORMot.pas.
20942 20943 20944 20945 20946 20947 20948 20949 20950 20951 20952 20953 20954 20955 20956 ..... 20973 20974 20975 20976 20977 20978 20979 20980 20981 20982 20983 20984 20985 20986 20987 20988 ..... 48599 48600 48601 48602 48603 48604 48605 48606 48607 48608 48609 48610 48611 48612 ..... 48619 48620 48621 48622 48623 48624 48625 48626 48627 48628 48629 48630 48631 48632 ..... 48635 48636 48637 48638 48639 48640 48641 48642 48643 48644 48645 48646 48647 48648 ..... 48670 48671 48672 48673 48674 48675 48676 48677 48678 48679 48680 48681 48682 48683 48684 48685 ..... 48686 48687 48688 48689 48690 48691 48692 48693 48694 48695 48696 48697 48698 48699 48700 48701 ..... 48713 48714 48715 48716 48717 48718 48719 48720 48721 48722 48723 48724 48725 48726 48727 48728 |
begin if self=nil then result := 0 else result := fRowCount; end; procedure TSQLTable.InitFieldTypes; var f,i: integer; FieldType: TSQLFieldType; FieldTypeInfo: pointer; TableInd: integer; U: PPUTF8Char; begin if Assigned(fQueryColumnTypes) and (FieldCount<>length(fQueryColumnTypes)) then raise ESQLTableException.CreateUTF8('%.CreateWithColumnTypes() called with % '+ ................................................................................ if f in fFieldParsedAsString then begin // the parser identified as string value -> check if was sftDateTime FieldType := sftUTF8Text; U := @fResults[FieldCount+f]; for i := 1 to fRowCount do if U^=nil then // search for a non void column inc(U,FieldCount) else begin if Iso8601ToTimeLogPUTF8Char(U^,0)<>0 then FieldType := sftDateTime; // this was a ISO-8601 date/time value break; end; end else begin U := @fResults[FieldCount+f]; for i := 1 to fRowCount do begin FieldType := UTF8ContentNumberType(U^); inc(U,FieldCount); ................................................................................ // auto-create published persistent class instances for i := 0 to fields.ClassesCount-1 do with fields.Classes[i] do PObject(PtrUInt(self)+Offset)^ := Instance.CreateNew; end; procedure AutoDestroyFields(self: TObject); var i: integer; fields: TAutoCreateFields; begin fields := PPointer(PPtrInt(self)^+vmtAutoTable)^; if fields=nil then exit; // may happen in a weird finalization code // auto-release published persistent class instances ................................................................................ { TPersistentAutoCreateFields } constructor TPersistentAutoCreateFields.Create; begin AutoCreateFields(self); end; destructor TPersistentAutoCreateFields.Destroy; begin AutoDestroyFields(self); inherited Destroy; end; ................................................................................ { TSynAutoCreateFields } {$ifdef FPC_OR_PUREPASCAL} constructor TSynAutoCreateFields.Create; begin AutoCreateFields(self); end; {$else} class function TSynAutoCreateFields.NewInstance: TObject; asm push eax // class ................................................................................ end; { TInterfacedObjectAutoCreateFields } constructor TInterfacedObjectAutoCreateFields.Create; begin inherited Create; AutoCreateFields(self); end; destructor TInterfacedObjectAutoCreateFields.Destroy; begin AutoDestroyFields(self); inherited Destroy; end; ................................................................................ { TInjectableAutoCreateFields } constructor TInjectableAutoCreateFields.Create; var Inject: IAutoCreateFieldsResolve; begin inherited Create; // will auto-inject its dependencies (DI/IoC) AutoCreateFields(self); if TryResolve(TypeInfo(IAutoCreateFieldsResolve),Inject) then Inject.SetProperties(self); end; destructor TInjectableAutoCreateFields.Destroy; begin AutoDestroyFields(self); ................................................................................ end; { TCollectionItemAutoCreateFields } constructor TCollectionItemAutoCreateFields.Create(Collection: TCollection); begin inherited Create(Collection); AutoCreateFields(self); end; destructor TCollectionItemAutoCreateFields.Destroy; begin AutoDestroyFields(self); inherited Destroy; end; |
| > | | > > > < > < > < > |
20942 20943 20944 20945 20946 20947 20948 20949 20950 20951 20952 20953 20954 20955 20956 ..... 20973 20974 20975 20976 20977 20978 20979 20980 20981 20982 20983 20984 20985 20986 20987 20988 20989 ..... 48600 48601 48602 48603 48604 48605 48606 48607 48608 48609 48610 48611 48612 48613 48614 ..... 48621 48622 48623 48624 48625 48626 48627 48628 48629 48630 48631 48632 48633 48634 48635 ..... 48638 48639 48640 48641 48642 48643 48644 48645 48646 48647 48648 48649 48650 48651 48652 ..... 48674 48675 48676 48677 48678 48679 48680 48681 48682 48683 48684 48685 48686 48687 48688 48689 ..... 48690 48691 48692 48693 48694 48695 48696 48697 48698 48699 48700 48701 48702 48703 48704 48705 ..... 48717 48718 48719 48720 48721 48722 48723 48724 48725 48726 48727 48728 48729 48730 48731 48732 |
begin if self=nil then result := 0 else result := fRowCount; end; procedure TSQLTable.InitFieldTypes; var f,i,len: integer; FieldType: TSQLFieldType; FieldTypeInfo: pointer; TableInd: integer; U: PPUTF8Char; begin if Assigned(fQueryColumnTypes) and (FieldCount<>length(fQueryColumnTypes)) then raise ESQLTableException.CreateUTF8('%.CreateWithColumnTypes() called with % '+ ................................................................................ if f in fFieldParsedAsString then begin // the parser identified as string value -> check if was sftDateTime FieldType := sftUTF8Text; U := @fResults[FieldCount+f]; for i := 1 to fRowCount do if U^=nil then // search for a non void column inc(U,FieldCount) else begin len := StrLen(U^); if (len>=15) and (Iso8601ToTimeLogPUTF8Char(U^,len)<>0) then FieldType := sftDateTime; // e.g. YYYYMMDDThhmmss date/time value break; end; end else begin U := @fResults[FieldCount+f]; for i := 1 to fRowCount do begin FieldType := UTF8ContentNumberType(U^); inc(U,FieldCount); ................................................................................ // auto-create published persistent class instances for i := 0 to fields.ClassesCount-1 do with fields.Classes[i] do PObject(PtrUInt(self)+Offset)^ := Instance.CreateNew; end; procedure AutoDestroyFields(self: TObject); {$ifdef HASINLINE}inline;{$endif} var i: integer; fields: TAutoCreateFields; begin fields := PPointer(PPtrInt(self)^+vmtAutoTable)^; if fields=nil then exit; // may happen in a weird finalization code // auto-release published persistent class instances ................................................................................ { TPersistentAutoCreateFields } constructor TPersistentAutoCreateFields.Create; begin AutoCreateFields(self); inherited Create; // always call the virtual constructor end; destructor TPersistentAutoCreateFields.Destroy; begin AutoDestroyFields(self); inherited Destroy; end; ................................................................................ { TSynAutoCreateFields } {$ifdef FPC_OR_PUREPASCAL} constructor TSynAutoCreateFields.Create; begin AutoCreateFields(self); inherited Create; // always call the virtual constructor end; {$else} class function TSynAutoCreateFields.NewInstance: TObject; asm push eax // class ................................................................................ end; { TInterfacedObjectAutoCreateFields } constructor TInterfacedObjectAutoCreateFields.Create; begin AutoCreateFields(self); inherited Create; // always call the virtual constructor end; destructor TInterfacedObjectAutoCreateFields.Destroy; begin AutoDestroyFields(self); inherited Destroy; end; ................................................................................ { TInjectableAutoCreateFields } constructor TInjectableAutoCreateFields.Create; var Inject: IAutoCreateFieldsResolve; begin AutoCreateFields(self); inherited Create; // overriden method will inject its dependencies (DI/IoC) if TryResolve(TypeInfo(IAutoCreateFieldsResolve),Inject) then Inject.SetProperties(self); end; destructor TInjectableAutoCreateFields.Destroy; begin AutoDestroyFields(self); ................................................................................ end; { TCollectionItemAutoCreateFields } constructor TCollectionItemAutoCreateFields.Create(Collection: TCollection); begin AutoCreateFields(self); inherited Create(Collection); end; destructor TCollectionItemAutoCreateFields.Destroy; begin AutoDestroyFields(self); inherited Destroy; end; |
Changes to SynCommons.pas.
24869 24870 24871 24872 24873 24874 24875 24876 24877 24878 24879 24880 24881 24882 ..... 24885 24886 24887 24888 24889 24890 24891 24892 24893 24894 24895 24896 24897 24898 24899 24900 ..... 25158 25159 25160 25161 25162 25163 25164 25165 25166 25167 25168 25169 25170 25171 25172 25173 25174 25175 25176 25177 25178 25179 ..... 25336 25337 25338 25339 25340 25341 25342 25343 25344 25345 25346 25347 25348 25349 25350 25351 25352 25353 25354 25355 25356 25357 25358 25359 25360 25361 25362 25363 25364 |
if P[4] in ['-','/'] then begin inc(P); dec(L); end; // allow YYYY-MM-DD D := 1; if L>=6 then begin // YYYYMM M := ord(P[4])*10+ord(P[5])-(48+480); if (M=0) or (M>12) then exit; if P[6] in ['-','/'] then begin inc(P); dec(L); end; // allow YYYY-MM-DD if L>=8 then begin // YYYYMMDD D := ord(P[6])*10+ord(P[7])-(48+480); if (D=0) or (D>MonthDays[true][M]) then exit; // worse is leap year=true end; end else M := 1; if M>2 then // inlined EncodeDate(Y,M,D) dec(M,3) else ................................................................................ dec(Y); end; if Y>9999 then exit; // avoid integer overflow e.g. if '0000' is an invalid date with Div100(Y) do unaligned(result) := (146097*YDiv100) shr 2 + (1461*YMod100) shr 2 + (153*M+2) div 5+D-693900; if (L<15) or not(P[8] in [' ','T']) then exit; end; H := ord(P[9])*10+ord(P[10])-(48+480); if P[11]=':' then inc(P); // allow hh:mm:ss MI := ord(P[11])*10+ord(P[12])-(48+480); if P[13]=':' then inc(P); // allow hh:mm:ss SS := ord(P[13])*10+ord(P[14])-(48+480); if (H<24) and (MI<60) and (SS<60) then // inlined EncodeTime() ................................................................................ inc(result,V shl 22) else begin result := 0; exit; end; if P[6] in ['-','/'] then begin inc(P); dec(L); end; // allow YYYY-MM-DD if L>=8 then begin // YYYYMMDD V := ord(P[6])*10+ord(P[7])-(48+480+1); // Day 1..31 -> 0..30 if V<=30 then inc(result,V shl 17) else begin result := 0; exit; end; end; end; if (L<15) or not(P[8] in [' ','T']) then begin if ContainsNoTime<>nil then ContainsNoTime^ := true; exit; end; end; if ContainsNoTime<>nil then ContainsNoTime^ := false; ................................................................................ (Int64Rec(Value).Lo shr 6) and 63, Int64Rec(Value).Lo and 63, 0); end; function TryEncodeDate(Year, Month, Day: Word; out Date: TDateTime): Boolean; begin // faster version by AB Result := False; if (Month < 1) or (Month > 12) then exit; if (Day <= MonthDays[((Year and 3) = 0) and ((Year mod 100 > 0) or (Year mod 400 = 0))][Month]) and (Year >= 1) and (Year < 10000) and (Month < 13) and (Day > 0) then begin if Month > 2 then Dec (Month, 3) else if (Month > 0) then begin Inc (Month, 9); Dec (Year); end else exit; // Month <= 0 with Div100(Year) do Date := (146097 * YDiv100) shr 2 + (1461 * YMod100) shr 2 + (153 * Month + 2) div 5 + Day - 693900; result := true; end; end; function TTimeLogBits.ToDate: TDateTime; var Y: cardinal; begin |
> > | | | | | | | | | | | | | | | | |
24869 24870 24871 24872 24873 24874 24875 24876 24877 24878 24879 24880 24881 24882 24883 24884 ..... 24887 24888 24889 24890 24891 24892 24893 24894 24895 24896 24897 24898 24899 24900 24901 24902 ..... 25160 25161 25162 25163 25164 25165 25166 25167 25168 25169 25170 25171 25172 25173 25174 25175 25176 25177 25178 25179 25180 25181 ..... 25338 25339 25340 25341 25342 25343 25344 25345 25346 25347 25348 25349 25350 25351 25352 25353 25354 25355 25356 25357 25358 25359 25360 25361 25362 25363 25364 25365 25366 |
if P[4] in ['-','/'] then begin inc(P); dec(L); end; // allow YYYY-MM-DD D := 1; if L>=6 then begin // YYYYMM M := ord(P[4])*10+ord(P[5])-(48+480); if (M=0) or (M>12) then exit; if P[6] in ['-','/'] then begin inc(P); dec(L); end; // allow YYYY-MM-DD if L>=8 then begin // YYYYMMDD if not(P[8] in [#0,' ','T']) then exit; // invalid date format D := ord(P[6])*10+ord(P[7])-(48+480); if (D=0) or (D>MonthDays[true][M]) then exit; // worse is leap year=true end; end else M := 1; if M>2 then // inlined EncodeDate(Y,M,D) dec(M,3) else ................................................................................ dec(Y); end; if Y>9999 then exit; // avoid integer overflow e.g. if '0000' is an invalid date with Div100(Y) do unaligned(result) := (146097*YDiv100) shr 2 + (1461*YMod100) shr 2 + (153*M+2) div 5+D-693900; if L<15 then exit; // not enough space to retrieve the time end; H := ord(P[9])*10+ord(P[10])-(48+480); if P[11]=':' then inc(P); // allow hh:mm:ss MI := ord(P[11])*10+ord(P[12])-(48+480); if P[13]=':' then inc(P); // allow hh:mm:ss SS := ord(P[13])*10+ord(P[14])-(48+480); if (H<24) and (MI<60) and (SS<60) then // inlined EncodeTime() ................................................................................ inc(result,V shl 22) else begin result := 0; exit; end; if P[6] in ['-','/'] then begin inc(P); dec(L); end; // allow YYYY-MM-DD if L>=8 then begin // YYYYMMDD V := ord(P[6])*10+ord(P[7])-(48+480+1); // Day 1..31 -> 0..30 if (V<=30) and(P[8] in [#0,' ','T']) then inc(result,V shl 17) else begin result := 0; exit; end; end; end; if L<15 then begin // not enough place to retrieve a time if ContainsNoTime<>nil then ContainsNoTime^ := true; exit; end; end; if ContainsNoTime<>nil then ContainsNoTime^ := false; ................................................................................ (Int64Rec(Value).Lo shr 6) and 63, Int64Rec(Value).Lo and 63, 0); end; function TryEncodeDate(Year, Month, Day: Word; out Date: TDateTime): Boolean; begin // faster version by AB Result := False; if (Month<1) or (Month>12) then exit; if (Day <= MonthDays[ ((Year and 3)=0) and ((Year mod 100>0) or (Year mod 400=0))][Month]) and (Year>=1) and (Year<10000) and (Month<13) and (Day>0) then begin if Month>2 then dec(Month,3) else if (Month>0) then begin inc(Month,9); dec(Year); end else exit; // Month <= 0 with Div100(Year) do Date := (146097*YDiv100) shr 2+(1461*YMod100) shr 2+ (153*Month+2) div 5+Day-693900; result := true; end; end; function TTimeLogBits.ToDate: TDateTime; var Y: cardinal; begin |
Changes to SynSelfTests.pas.
3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 .... 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 .... 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 |
tmp := 'T06:03:20'; Check(Iso8601CheckAndDecode(Pointer(tmp),length(tmp),D)); Check(TimeToIso8601(D,true)=tmp); tmp := '1982-10-30 06:03:20'; Check(not Iso8601CheckAndDecode(Pointer(tmp),length(tmp),D)); tmp := 'T06:03:2a'; Check(not Iso8601CheckAndDecode(Pointer(tmp),length(tmp),D)); end; procedure TTestLowLevelCommon.TimeZones; var tz: TSynTimeZone; d: TTimeZoneData; i,bias: integer; hdl,reload: boolean; ................................................................................ procedure Test(const LOG: RawUTF8; ExpectedDate: TDateTime); var L: TSynLogFile; begin L := TSynLogFile.Create(pointer(LOG),length(LOG)); try Check(L.ExecutableName='D:\Dev\lib\SQLite3\exe\TestSQL3.exe'); Check(L.ExecutableVersion='1.2.3.4'); if ExpectedDate=40640 then Check(L.InstanceName='D:\Dev\MyLibrary.dll') else Check(L.InstanceName=''); CheckSame(L.ExecutableDate,ExpectedDate,1e-7); Check(L.ComputerHost='MyPC'); Check(L.LevelUsed=[sllEnter,sllLeave,sllDebug]); Check(L.RunningUser='MySelf'); Check(L.CPU='2*0-15-1027'); ................................................................................ Check(L.LogProc[0].Index=0); Check(L.LogProc[0].Time=10020006); finally L.Free; end; end; begin Test('D:\Dev\lib\SQLite3\exe\TestSQL3.exe 1.2.3.4 (2011-04-07)'#13#10+ 'Host=MyPC User=MySelf CPU=2*0-15-1027 OS=2.3=5.1.2600 Wow64=0 Freq=3579545 '+ 'Instance=D:\Dev\MyLibrary.dll'#13#10+ 'TSynLog 1.15 LVCL 2011-04-07 12:04:09'#13#10#13#10+ '20110407 12040903 + SQLite3Commons.TSQLRestServer.URI (14163)'#13#10+ '20110407 12040904 debug {"TObjectList(00AF8D00)":["TObjectList(00AF8D20)",'+ '"TObjectList(00AF8D60)","TFileVersion(00ADC0B0)","TSynMapFile(00ACC990)"]}'#13#10+ '20110407 12040915 - SQLite3Commons.TSQLRestServer.URI (14163) 10.020.006', 40640); Test('D:\Dev\lib\SQLite3\exe\TestSQL3.exe 1.2.3.4 (2011-04-07 11:09:06)'#13#10+ 'Host=MyPC User=MySelf CPU=2*0-15-1027 OS=2.3=5.1.2600 Wow64=0 Freq=3579545'#13#10+ 'TSynLog 1.15 LVCL 2011-04-07 12:04:09'#13#10#13#10+ '20110407 12040903 + SQLite3Commons.TSQLRestServer.URI (14163)'#13#10+ '20110407 12040904 debug {"TObjectList(00AF8D00)":["TObjectList(00AF8D20)",'+ '"TObjectList(00AF8D60)","TFileVersion(00ADC0B0)","TSynMapFile(00ACC990)"]}'#13#10+ '20110407 12040915 - SQLite3Commons.TSQLRestServer.URI (14163) 10.020.006', 40640.464653); end; procedure TTestLowLevelCommon._TObjectListHashed; const MAX = 1000000; var obj: TObjectListHashed; i: PtrInt; added: boolean; |
> > > | | | | | |
3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 .... 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 .... 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 |
tmp := 'T06:03:20'; Check(Iso8601CheckAndDecode(Pointer(tmp),length(tmp),D)); Check(TimeToIso8601(D,true)=tmp); tmp := '1982-10-30 06:03:20'; Check(not Iso8601CheckAndDecode(Pointer(tmp),length(tmp),D)); tmp := 'T06:03:2a'; Check(not Iso8601CheckAndDecode(Pointer(tmp),length(tmp),D)); tmp := '1435051262-45869-63626'; check(Iso8601ToDateTime(tmp)=0); check(Iso8601ToTimelog(tmp)=0); end; procedure TTestLowLevelCommon.TimeZones; var tz: TSynTimeZone; d: TTimeZoneData; i,bias: integer; hdl,reload: boolean; ................................................................................ procedure Test(const LOG: RawUTF8; ExpectedDate: TDateTime); var L: TSynLogFile; begin L := TSynLogFile.Create(pointer(LOG),length(LOG)); try Check(L.ExecutableName='D:\Dev\lib\SQLite3\exe\TestSQL3.exe'); Check(L.ExecutableVersion='1.2.3.4'); if trunc(ExpectedDate)=40640 then Check(L.InstanceName='D:\Dev\MyLibrary.dll') else Check(L.InstanceName=''); CheckSame(L.ExecutableDate,ExpectedDate,1e-7); Check(L.ComputerHost='MyPC'); Check(L.LevelUsed=[sllEnter,sllLeave,sllDebug]); Check(L.RunningUser='MySelf'); Check(L.CPU='2*0-15-1027'); ................................................................................ Check(L.LogProc[0].Index=0); Check(L.LogProc[0].Time=10020006); finally L.Free; end; end; begin Test('D:\Dev\lib\SQLite3\exe\TestSQL3.exe 1.2.3.4 (2011-04-07 11:09:06)'#13#10+ 'Host=MyPC User=MySelf CPU=2*0-15-1027 OS=2.3=5.1.2600 Wow64=0 Freq=3579545 '+ 'Instance=D:\Dev\MyLibrary.dll'#13#10+ 'TSynLog 1.15 LVCL 2011-04-07 12:04:09'#13#10#13#10+ '20110407 12040903 + SQLite3Commons.TSQLRestServer.URI (14163)'#13#10+ '20110407 12040904 debug {"TObjectList(00AF8D00)":["TObjectList(00AF8D20)",'+ '"TObjectList(00AF8D60)","TFileVersion(00ADC0B0)","TSynMapFile(00ACC990)"]}'#13#10+ '20110407 12040915 - SQLite3Commons.TSQLRestServer.URI (14163) 10.020.006', 40640.464653); Test('D:\Dev\lib\SQLite3\exe\TestSQL3.exe 1.2.3.4 (2011-04-08 11:09:06)'#13#10+ 'Host=MyPC User=MySelf CPU=2*0-15-1027 OS=2.3=5.1.2600 Wow64=0 Freq=3579545'#13#10+ 'TSynLog 1.15 LVCL 2011-04-07 12:04:09'#13#10#13#10+ '20110407 12040903 + SQLite3Commons.TSQLRestServer.URI (14163)'#13#10+ '20110407 12040904 debug {"TObjectList(00AF8D00)":["TObjectList(00AF8D20)",'+ '"TObjectList(00AF8D60)","TFileVersion(00ADC0B0)","TSynMapFile(00ACC990)"]}'#13#10+ '20110407 12040915 - SQLite3Commons.TSQLRestServer.URI (14163) 10.020.006', 40641.464653); end; procedure TTestLowLevelCommon._TObjectListHashed; const MAX = 1000000; var obj: TObjectListHashed; i: PtrInt; added: boolean; |
Changes to SynopseCommit.inc.
1 |
'1.18.1535'
|
| |
1 |
'1.18.1536'
|