Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-5944

modifier failure with empty string field name and nested fields

    • Type: Icon: Bug Bug
    • Resolution: Duplicate
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: 2.0.5
    • Component/s: Write Ops
    • Labels:
    • Environment:
      Tests with CLI PHP but confirmed most on shell, too. Two environments checked: Single mongod v2.0.3 on OSX, and v2.0.5 on Linux (EC2 micro instance 2.6.35.14).
    • Query
    • ALL

      Test:

      t.save( { a:{ '':1 } } );
      t.update( {}, { $set:{ 'a.b':2 } } );
      printjson( db.getLastError() );
      printjson( t.findOne() );
      

      Documents or subdocuments with empty string keys can cause $set updates to that document to fail.

      Specifically, $set ing a new field at the same level as an empty-string key, will silently fail. Same for updates to children of siblings to empty-string key ("nephew/niece" fields).

      This behaviour sometimes changes depending on the number of updates inside $set.

      The test script output should make it clear enough:

          • Single - $set updates *** //php test.php 1 multi_tests
            [...]
            	*** TEST 3 ***
            original:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2}}}
            update: 	{"$set":{"tags.m.new":1}}
            expected:	{"_id":"1","tags":{"":{"oops":1},"m":{"new":1,"rock":1},"o":{"funny":2}}}
            received:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2}}}
            	Test FAILED
            
            	*** TEST 4 ***
            original:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2}}}
            update: 	{"$set":{"tags.p.p":10}}
            expected:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2},"p":{"p":10}}}
            received:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2}}}
            	Test FAILED
            
            	*** TEST 5 ***
            original:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2}}}
            update: 	{"$set":{"tags.p":1}}
            expected:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2},"p":1}}
            received:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2}}}
            	Test FAILED
            
            	*** TEST 6 ***
            original:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2}}}
            update: 	{"$set":{"tags.other":10}}
            expected:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2},"other":10}}
            received:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2}}}
            	Test FAILED
            

            *** Multi - $set updates *** //php test.php 1 multi_tests
            [...]

            	*** TEST 3 ***
            original:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2}}}
            update: 	{"$set":{"tags.m.new":1,"tags.m.newer":1}}
            expected:	{"_id":"1","tags":{"":{"oops":1},"m":{"new":1,"newer":1,"rock":1},"o":{"funny":2}}}
            received:	{"_id":"1","tags":{"":{"oops":1},"m":{"new":1,"newer":1,"rock":1},"o":{"funny":2}}}
            	Test passed //no problem creating two new tags (one had failed)
            
            	*** TEST 4 ***
            original:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2}}}
            update: 	{"$set":{"tags.p.p":10,"tags.p.q":11}}
            expected:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2},"p":{"p":10,"q":11}}}
            received:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2},"p":{"p":10,"q":11}}}
            	Test passed
            
            	*** TEST 5 ***
            original:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2}}}
            update: 	{"$set":{"tags.p":1,"tags.q":1}}
            expected:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2},"p":1,"q":1}}
            received:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2},"q":1}}
            	Test FAILED //note one update made it through
            
            	*** TEST 6 ***
            original:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2}}}
            update: 	{"$set":{"tags.other":10,"tags.music":11}}
            expected:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"music":11,"o":{"funny":2},"other":10}}
            received:	{"_id":"1","tags":{"":{"oops":1},"m":{"rock":1},"o":{"funny":2},"other":10}}
            	Test FAILED //note one update made it through
            

      If the empty-string fields are removed from the original object, all tests succeed (run with 0 instead of 1)

      Attached tests are PHP (PHPMongo 1.2.9) but behaviour is the same on the shell.

        1. multi-set.log
          5 kB
          Tasos Bitsios
        2. single-set.log
          4 kB
          Tasos Bitsios
        3. test-update-emptystringkey.tgz
          3 kB
          Tasos Bitsios

            Assignee:
            backlog-server-query Backlog - Query Team (Inactive)
            Reporter:
            yourad_io Tasos Bitsios
            Votes:
            1 Vote for this issue
            Watchers:
            9 Start watching this issue

              Created:
              Updated:
              Resolved: