summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristina Chodorow <k@ubuntu.(none)>2010-08-26 15:17:41 -0400
committerMathias Stearn <mathias@10gen.com>2010-11-03 17:30:33 -0400
commit0c92fea8d7cb5c2807ec5ccad140b18d04cdee10 (patch)
tree6a7208cf7d81796951b8c4f51a706418b12c9ed4
parente1ef4d5c551f376b7302e12bda6cc11c20954a60 (diff)
downloadmongo-0c92fea8d7cb5c2807ec5ccad140b18d04cdee10.tar.gz
fix set with large ints SERVER-1347
-rw-r--r--jstests/updatee.js71
-rw-r--r--util/goodies.h35
2 files changed, 98 insertions, 8 deletions
diff --git a/jstests/updatee.js b/jstests/updatee.js
new file mode 100644
index 00000000000..228eba018d6
--- /dev/null
+++ b/jstests/updatee.js
@@ -0,0 +1,71 @@
+// big numeric updates (used to overflow)
+
+t = db.updatee;
+t.drop();
+
+var o = { "_id" : 1,
+ "actual" : {
+ "key1" : "val1",
+ "key2" : "val2",
+ "001" : "val3",
+ "002" : "val4",
+ "0020000000000000000000" : "val5"
+ },
+ "profile-id" : "test" };
+
+
+t.insert( o );
+assert.eq( o , t.findOne() , "A1" );
+
+t.update({"profile-id" : "test"}, {$set: {"actual.0030000000000000000000": "val6"}});
+
+var q = t.findOne();
+
+// server-1347
+assert.eq(q.actual["0020000000000000000000"], "val5", "A2");
+assert.eq(q.actual["0030000000000000000000"], "val6", "A3");
+
+t.update({"profile-id" : "test"}, {$set: {"actual.02": "v4"}});
+
+q = t.findOne();
+assert.eq(q.actual["02"], "v4", "A4");
+assert(!q.actual["002"], "A5");
+
+t.update({"_id" : 1}, {$set : {"actual.2139043290148390248219423941.b" : 4}});
+q = t.findOne();
+assert.eq(q.actual["2139043290148390248219423941"].b, 4, "A6");
+
+// non-nested
+t.update({"_id" : 1}, {$set : {"7213647182934612837492342341" : 1}});
+t.update({"_id" : 1}, {$set : {"7213647182934612837492342342" : 2}});
+
+q = t.findOne();
+assert.eq(q["7213647182934612837492342341"], 1, "A7 1");
+assert.eq(q["7213647182934612837492342342"], 2, "A7 2");
+
+// 0s
+t.update({"_id" : 1}, {$set : {"actual.000" : "val000"}});
+q = t.findOne();
+assert.eq(q.actual["000"], "val000", "A8 zeros");
+
+t.update({"_id" : 1}, {$set : {"actual.00" : "val00"}});
+q = t.findOne();
+assert.eq(q.actual["00"], "val00", "A8 00");
+assert(!q.actual["000"], "A9");
+
+t.update({"_id" : 1}, {$set : {"actual.000" : "val000"}});
+q = t.findOne();
+assert.eq(q.actual["000"], "val000", "A9");
+assert(!q.actual["00"], "A10");
+
+t.update({"_id" : 1}, {$set : {"actual.01" : "val01"}});
+q = t.findOne();
+assert.eq(q.actual["000"], "val000", "A11");
+assert.eq(q.actual["01"], "val01", "A12");
+
+// shouldn't work, but shouldn't do anything too heinous, either
+t.update({"_id" : 1}, {$set : {"0.." : "val01"}});
+t.update({"_id" : 1}, {$set : {"0..0" : "val01"}});
+t.update({"_id" : 1}, {$set : {".0" : "val01"}});
+t.update({"_id" : 1}, {$set : {"..0" : "val01"}});
+t.update({"_id" : 1}, {$set : {"0.0..0" : "val01"}});
diff --git a/util/goodies.h b/util/goodies.h
index 0bbc4da499e..7b739968e24 100644
--- a/util/goodies.h
+++ b/util/goodies.h
@@ -666,16 +666,35 @@ namespace mongo {
bool n2 = isNumber( *s2 );
if ( n1 && n2 ) {
- char * e1;
- char * e2;
- long l1 = strtol( s1 , &e1 , 10 );
- long l2 = strtol( s2 , &e2 , 10 );
-
- if ( l1 > l2 )
+ // get rid of leading 0s
+ while ( *s1 == '0' ) s1++;
+ while ( *s2 == '0' ) s2++;
+
+ char * e1 = (char*)s1;
+ char * e2 = (char*)s2;
+
+ // find length
+ // if end of string, will break immediately ('\0')
+ while ( isNumber (*e1) ) e1++;
+ while ( isNumber (*e2) ) e2++;
+
+ int len1 = e1-s1;
+ int len2 = e2-s2;
+
+ int result;
+ // if one is longer than the other, return
+ if ( len1 > len2 ) {
return 1;
- else if ( l1 < l2 )
+ }
+ else if ( len2 > len1 ) {
return -1;
-
+ }
+ // if the lengths are equal, just strcmp
+ else if ( (result = strncmp(s1, s2, len1)) != 0 ) {
+ return result;
+ }
+
+ // otherwise, the numbers are equal
s1 = e1;
s2 = e2;
continue;