Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | data sent to MongoDB from JSON will now recognize strict 'YYYY-MM-DDThh:mm:ss' or 'YYYY-MM-DD' or 'Thh:mm:ss' patterns as betDateTime, as e.g. generated by TTextWriter.AddDateTime() or RecordSaveJSON() |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
2d3aef367e454c44d2e203a3159c82bf |
User & Date: | User 2014-05-24 09:39:20 |
2014-05-24
| ||
14:13 | StrLen() function will now use faster SSE2 instructions on supported CPUs check-in: 840adacf7c user: User tags: trunk | |
09:39 | data sent to MongoDB from JSON will now recognize strict 'YYYY-MM-DDThh:mm:ss' or 'YYYY-MM-DD' or 'Thh:mm:ss' patterns as betDateTime, as e.g. generated by TTextWriter.AddDateTime() or RecordSaveJSON() check-in: 2d3aef367e user: User tags: trunk | |
09:36 | added Iso8601CheckAndDecode() function check-in: 447234b233 user: User tags: trunk | |
Changes to SynMongoDB.pas.
442 443 444 445 446 447 448 449 450 451 452 453 454 455 .... 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 .... 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 .... 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 |
procedure BSONWrite(const name: RawUTF8; const value: integer); overload; /// write a 64 bit integer value procedure BSONWrite(const name: RawUTF8; const value: Int64); overload; /// write a string (UTF-8) value procedure BSONWrite(const name: RawUTF8; const value: RawUTF8; isJavaScript: boolean=false); overload; /// write a string (UTF-8) value from a memory buffer procedure BSONWrite(const name: RawUTF8; value: PUTF8Char); overload; /// write a binary (BLOB) value procedure BSONWrite(const name: RawUTF8; Data: pointer; DataLen: integer); overload; /// write an ObjectID value procedure BSONWrite(const name: RawUTF8; const value: TBSONObjectID); overload; /// write a RegEx value procedure BSONWriteRegEx(const name: RawUTF8; const RegEx: RawByteString); /// write a data/time value ................................................................................ BSONWrite(name,betString); L := StrLen(Value)+1; Write4(L); if L=1 then Write1(0) else Write(value,L); end; procedure TBSONWriter.BSONWriteDateTime(const name: RawUTF8; const value: TDateTime); var UnixTime: Int64; begin UnixTime := DateTimeToUnixMSTime(value); BSONWrite(name,betDateTime); Write8(UnixTime); ................................................................................ procedure TBSONWriter.BSONWriteFromJSON(const name: RawUTF8; var JSON: PUTF8Char; EndOfObject: PUTF8Char; DoNotTryExtendedMongoSyntax: boolean); var tmp: variant; // we use a local variant for only BSONVariant values blob: RawByteString; wasString: boolean; err: integer; Value, Dot: PUTF8Char; VDouble: double; Kind: TBSONElementType; begin if JSON^ in [#1..' '] then repeat inc(JSON) until not(JSON^ in [#1..' ']); if (not DoNotTryExtendedMongoSyntax) and BSONVariantType.TryJSONToVariant(JSON,tmp,EndOfObject) then // was betDateTime, betObjectID or betRegEx, from strict or extended JSON ................................................................................ VDouble := GetExtended(Value,err); if err=0 then begin // floating-point number BSONWrite(name,VDouble); exit; end; end; // found no numerical value -> check text value if Base64MagicCheckAndDecode(Value,blob) then // recognized '\uFFF0base64encodedbinary' pattern BSONWrite(name,pointer(blob),length(blob)) else // will point to the in-place escaped JSON text BSONWrite(name,Value); end; end; if TotalWritten>BSON_MAXDOCUMENTSIZE then raise EBSONException.CreateFmt('BSON document size = %d > maximum %d', [TotalWritten,BSON_MAXDOCUMENTSIZE]); end; |
> > > > > > > > > > > > > > > | > > > | |
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 .... 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 .... 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 .... 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 |
procedure BSONWrite(const name: RawUTF8; const value: integer); overload; /// write a 64 bit integer value procedure BSONWrite(const name: RawUTF8; const value: Int64); overload; /// write a string (UTF-8) value procedure BSONWrite(const name: RawUTF8; const value: RawUTF8; isJavaScript: boolean=false); overload; /// write a string (UTF-8) value from a memory buffer procedure BSONWrite(const name: RawUTF8; value: PUTF8Char); overload; /// write a string (UTF-8) value from a memory buffer procedure BSONWriteString(const name: RawUTF8; value: PUTF8Char; valueLen: integer); /// write a binary (BLOB) value procedure BSONWrite(const name: RawUTF8; Data: pointer; DataLen: integer); overload; /// write an ObjectID value procedure BSONWrite(const name: RawUTF8; const value: TBSONObjectID); overload; /// write a RegEx value procedure BSONWriteRegEx(const name: RawUTF8; const RegEx: RawByteString); /// write a data/time value ................................................................................ BSONWrite(name,betString); L := StrLen(Value)+1; Write4(L); if L=1 then Write1(0) else Write(value,L); end; procedure TBSONWriter.BSONWriteString(const name: RawUTF8; value: PUTF8Char; valueLen: integer); begin BSONWrite(name,betString); inc(valueLen); Write4(valueLen); if valueLen=1 then Write1(0) else Write(value,valueLen); end; procedure TBSONWriter.BSONWriteDateTime(const name: RawUTF8; const value: TDateTime); var UnixTime: Int64; begin UnixTime := DateTimeToUnixMSTime(value); BSONWrite(name,betDateTime); Write8(UnixTime); ................................................................................ procedure TBSONWriter.BSONWriteFromJSON(const name: RawUTF8; var JSON: PUTF8Char; EndOfObject: PUTF8Char; DoNotTryExtendedMongoSyntax: boolean); var tmp: variant; // we use a local variant for only BSONVariant values blob: RawByteString; wasString: boolean; err: integer; Value, Dot: PUTF8Char; ValueLen: integer; ValueDateTime: TDateTime; VDouble: double; Kind: TBSONElementType; begin if JSON^ in [#1..' '] then repeat inc(JSON) until not(JSON^ in [#1..' ']); if (not DoNotTryExtendedMongoSyntax) and BSONVariantType.TryJSONToVariant(JSON,tmp,EndOfObject) then // was betDateTime, betObjectID or betRegEx, from strict or extended JSON ................................................................................ VDouble := GetExtended(Value,err); if err=0 then begin // floating-point number BSONWrite(name,VDouble); exit; end; end; // found no numerical value -> check text value ValueLen := StrLen(Value); if Base64MagicCheckAndDecode(Value,ValueLen,blob) then // recognized '\uFFF0base64encodedbinary' pattern BSONWrite(name,pointer(blob),length(blob)) else if Iso8601CheckAndDecode(Value,ValueLen,ValueDateTime) then // recognized TTextWriter.AddDateTime() pattern BSONWriteDateTime(name,ValueDateTime) else // will point to the in-place escaped JSON text BSONWriteString(name,Value,ValueLen); end; end; if TotalWritten>BSON_MAXDOCUMENTSIZE then raise EBSONException.CreateFmt('BSON document size = %d > maximum %d', [TotalWritten,BSON_MAXDOCUMENTSIZE]); end; |
Changes to SynSelfTests.pas.
2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 .... 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 .... 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 |
procedure TTestLowLevelCommon.Iso8601DateAndTime; procedure Test(D: TDateTime; Expanded: boolean); var s,t: RawUTF8; E: TDateTime; I,J: TTimeLogBits; begin s := DateTimeToIso8601(D,Expanded); E := Iso8601ToDateTime(s); Check(Abs(D-E)<(1000/MSecsPerDay)); // we allow 999 ms error Check(Iso8601ToTimeLog(s)<>0); I.From(s); t := I.Text(Expanded); if t<>s then // we allow error on time = 00:00:00 -> I.Text = just date Check(I.Value and (1 shl (6+6+5)-1)=0) else ................................................................................ CheckSame(IntervalTextToDateTime('-20 06:03:20'),-20.252314,1e-6); Check(DateTimeToIso8601Text(IntervalTextToDateTime('+0 06:03:20'))='T06:03:20'); tmp := DateTimeToIso8601Text(IntervalTextToDateTime('+1 06:03:20')); Check(tmp='1899-12-31T06:03:20'); tmp := DateTimeToIso8601Text(IntervalTextToDateTime('-2 06:03:20')); Check(tmp='1899-12-28T06:03:20'); CheckSame(TimeLogToDateTime(135131870949),41578.477512,1e-5); end; procedure TTestLowLevelCommon._IdemPropName; const abcde: PUTF8Char = 'ABcdE'; abcdf: PUTF8Char = 'ABcdF'; var WinAnsi: WinAnsiString; begin ................................................................................ Check(BSONToJSON(BSONFieldSelector('a,b,c'))='{"a":1,"b":1,"c":1}'); Check(VariantSaveMongoJSON(BSONVariantFieldSelector(['a','b','c']),modMongoShell)='{a:1,b:1,c:1}'); Check(VariantSaveMongoJSON(BSONVariantFieldSelector('a,b,c'),modMongoShell)='{a:1,b:1,c:1}'); o := _Obj(['id',ObjectID(BSONID),'name','John','date',variant(d2)]); u := VariantSaveMongoJSON(o,modNoMongo); u2 := FormatUTF8('{"id":"%","name":"John","date":"%"}',[BSONID,st]); Check(u=u2); Check(VariantSaveJson(BSONVariant(u))=u); u := VariantSaveMongoJSON(o,modMongoShell); Check(u=FormatUTF8('{id:ObjectId("%"),name:"John",date:ISODate("%")}',[BSONID,st])); u3 := VariantSaveJson(BSONVariant(u)); u := VariantSaveJSON(o); Check(u=FormatUTF8('{"id":{"$oid":"%"},"name":"John","date":"%"}',[BSONID,st])); u := VariantSaveMongoJSON(o,modMongoStrict); Check(u=FormatUTF8('{"id":{"$oid":"%"},"name":"John","date":{"$date":"%"}}',[BSONID,st])); |
> > > > > > > > > > > > > > > > > | > > > |
2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 .... 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 .... 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 |
procedure TTestLowLevelCommon.Iso8601DateAndTime; procedure Test(D: TDateTime; Expanded: boolean); var s,t: RawUTF8; E: TDateTime; I,J: TTimeLogBits; begin s := DateTimeToIso8601(D,Expanded); if Expanded then begin Check(Iso8601CheckAndDecode(Pointer(s),length(s),E)); Check(Abs(D-E)<(1000/MSecsPerDay)); // we allow 999 ms error end; E := Iso8601ToDateTime(s); Check(Abs(D-E)<(1000/MSecsPerDay)); // we allow 999 ms error Check(Iso8601ToTimeLog(s)<>0); I.From(s); t := I.Text(Expanded); if t<>s then // we allow error on time = 00:00:00 -> I.Text = just date Check(I.Value and (1 shl (6+6+5)-1)=0) else ................................................................................ CheckSame(IntervalTextToDateTime('-20 06:03:20'),-20.252314,1e-6); Check(DateTimeToIso8601Text(IntervalTextToDateTime('+0 06:03:20'))='T06:03:20'); tmp := DateTimeToIso8601Text(IntervalTextToDateTime('+1 06:03:20')); Check(tmp='1899-12-31T06:03:20'); tmp := DateTimeToIso8601Text(IntervalTextToDateTime('-2 06:03:20')); Check(tmp='1899-12-28T06:03:20'); CheckSame(TimeLogToDateTime(135131870949),41578.477512,1e-5); tmp := '1982-10-30T06:03:20'; Check(Iso8601CheckAndDecode(Pointer(tmp),length(tmp),D)); Check(DateTimeToIso8601(D,true)=tmp); tmp := '1982-10-30'; Check(Iso8601CheckAndDecode(Pointer(tmp),length(tmp),D)); Check(DateToIso8601(D,true)=tmp); 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._IdemPropName; const abcde: PUTF8Char = 'ABcdE'; abcdf: PUTF8Char = 'ABcdF'; var WinAnsi: WinAnsiString; begin ................................................................................ Check(BSONToJSON(BSONFieldSelector('a,b,c'))='{"a":1,"b":1,"c":1}'); Check(VariantSaveMongoJSON(BSONVariantFieldSelector(['a','b','c']),modMongoShell)='{a:1,b:1,c:1}'); Check(VariantSaveMongoJSON(BSONVariantFieldSelector('a,b,c'),modMongoShell)='{a:1,b:1,c:1}'); o := _Obj(['id',ObjectID(BSONID),'name','John','date',variant(d2)]); u := VariantSaveMongoJSON(o,modNoMongo); u2 := FormatUTF8('{"id":"%","name":"John","date":"%"}',[BSONID,st]); Check(u=u2); u3 := VariantSaveJson(BSONVariant(u)); Check(u3=FormatUTF8('{"id":"%","name":"John","date":{"$date":"%"}}',[BSONID,st])); u3 := VariantSaveMongoJSON(BSONVariant(u),modNoMongo); Check(u3=u); u := VariantSaveMongoJSON(o,modMongoShell); Check(u=FormatUTF8('{id:ObjectId("%"),name:"John",date:ISODate("%")}',[BSONID,st])); u3 := VariantSaveJson(BSONVariant(u)); u := VariantSaveJSON(o); Check(u=FormatUTF8('{"id":{"$oid":"%"},"name":"John","date":"%"}',[BSONID,st])); u := VariantSaveMongoJSON(o,modMongoStrict); Check(u=FormatUTF8('{"id":{"$oid":"%"},"name":"John","date":{"$date":"%"}}',[BSONID,st])); |