diff options
author | Eliot Horowitz <eliot@10gen.com> | 2009-06-08 10:54:55 -0400 |
---|---|---|
committer | Eliot Horowitz <eliot@10gen.com> | 2009-06-08 10:54:55 -0400 |
commit | d5122c9b90ef1f45585e09c45610488ff76894cf (patch) | |
tree | 594907f6b0c1283cae0b45d50a3f2425ab8f7399 | |
parent | b6e455fd69c2cb9d2bb12b39c8cc721f2e5c3f61 (diff) | |
download | mongo-d5122c9b90ef1f45585e09c45610488ff76894cf.tar.gz |
change Map to use Map.get Map.put Map[] won't work
more tests for group
-rw-r--r-- | jstests/group1.js | 17 | ||||
-rw-r--r-- | jstests/map1.js | 23 | ||||
-rw-r--r-- | scripting/sm_db.cpp | 44 | ||||
-rw-r--r-- | shell/db.js | 10 | ||||
-rw-r--r-- | shell/utils.js | 50 |
5 files changed, 126 insertions, 18 deletions
diff --git a/jstests/group1.js b/jstests/group1.js new file mode 100644 index 00000000000..e7b1d5ef5d7 --- /dev/null +++ b/jstests/group1.js @@ -0,0 +1,17 @@ +t = db.group1; +t.drop(); + +t.save( { n : 1 , a : 1 } ); +t.save( { n : 2 , a : 1 } ); +t.save( { n : 3 , a : 2 } ); +t.save( { n : 4 , a : 2 } ); +t.save( { n : 5 , a : 2 } ); + + +res = t.group( { key : { a : true } , + reduce: function(obj,prev) { prev.count++; }, + initial: { count: 0 } + } + ); + +printjson( res ); diff --git a/jstests/map1.js b/jstests/map1.js new file mode 100644 index 00000000000..1e12f47bf3e --- /dev/null +++ b/jstests/map1.js @@ -0,0 +1,23 @@ + +function basic1( key , lookup , shouldFail){ + var m = new Map(); + m.put( key , 17 ); + + var out = m.get( lookup || key ); + + if ( ! shouldFail ){ + assert.eq( 17 , out , "basic1 missing: " + tojson( key ) ); + } + else { + assert.isnull( out , "basic1 not missing: " + tojson( key ) ); + } + +} + +basic1( 6 ) +basic1( "eliot" ) +basic1( { a : 1 } ); +basic1( { a : 1 , b : 1 } ) +basic1( { a : 1 } , { b : 1 } , true ) +basic1( { a : 1 , b : 1 } , { b : 1 , a : 1 } , true ) +basic1( { a : 1 } , { a : 2 } , true ); diff --git a/scripting/sm_db.cpp b/scripting/sm_db.cpp index acb13b38777..d76faf801bf 100644 --- a/scripting/sm_db.cpp +++ b/scripting/sm_db.cpp @@ -499,6 +499,48 @@ namespace mongo { { 0 } }; + // Map + + bool specialMapString( const string& s ){ + return s == "put" || s == "get" || s == "_get" || s == "values" || s == "_data" || s == "constructor" ; + } + + JSBool map_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){ + if ( argc > 0 ){ + JS_ReportError( cx , "Map takes no arguments" ); + return JS_FALSE; + } + + JSObject * array = JS_NewArrayObject( cx , 0 , 0 ); + assert( array ); + + jsval a = OBJECT_TO_JSVAL( array ); + JS_SetProperty( cx , obj , "_data" , &a ); + + return JS_TRUE; + } + + JSBool map_prop( JSContext *cx, JSObject *obj, jsval idval, jsval *vp ){ + Convertor c(cx); + if ( specialMapString( c.toString( idval ) ) ) + return JS_TRUE; + + log() << "illegal prop access: " << c.toString( idval ) << endl; + JS_ReportError( cx , "can't use array access with Map" ); + return JS_FALSE; + } + + JSClass map_class = { + "Map" , JSCLASS_HAS_PRIVATE , + map_prop, JS_PropertyStub, map_prop, map_prop, + JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub, + JSCLASS_NO_OPTIONAL_MEMBERS + }; + + JSFunctionSpec map_functions[] = { + { 0 } + }; + // ----- @@ -601,6 +643,8 @@ namespace mongo { assert( JS_InitClass( cx , global , 0 , ×tamp_class , 0 , 0 , 0 , 0 , 0 , 0 ) ); assert( JS_InitClass( cx , global , 0 , &minkey_class , 0 , 0 , 0 , 0 , 0 , 0 ) ); assert( JS_InitClass( cx , global , 0 , &maxkey_class , 0 , 0 , 0 , 0 , 0 , 0 ) ); + + assert( JS_InitClass( cx , global , 0 , &map_class , map_constructor , 0 , 0 , map_functions , 0 , 0 ) ); scope->exec( jsconcatcode ); } diff --git a/shell/db.js b/shell/db.js index 1c4b84f4a4f..978b7badb6d 100644 --- a/shell/db.js +++ b/shell/db.js @@ -356,7 +356,6 @@ DB.prototype.group = function(parmsObj) { while( c.hasNext() ) { var obj = c.next(); - var key = {}; if( parms.key ) { for( var i in parms.key ) @@ -365,17 +364,16 @@ DB.prototype.group = function(parmsObj) { else { key = parms.$keyf(obj); } - - var aggObj = map[key]; + var aggObj = map.get(key); if( aggObj == null ) { var newObj = Object.extend({}, key); // clone - aggObj = map[key] = Object.extend(newObj, parms.initial) + aggObj = Object.extend(newObj, parms.initial) + map.put( key , aggObj ); } parms.$reduce(obj, aggObj); } - var ret = map.values(); - return ret; + return map.values(); } var parms = Object.extend({}, parmsObj); diff --git a/shell/utils.js b/shell/utils.js index 88da9e9b374..ea0b8208fbd 100644 --- a/shell/utils.js +++ b/shell/utils.js @@ -1,4 +1,15 @@ +friendlyEqual = function( a , b ){ + if ( a == b ) + return true; + + if ( tojson( a ) == tojson( b ) ) + return true; + + return false; +} + + assert = function( b , msg ){ if ( b ) return; @@ -10,8 +21,7 @@ assert.eq = function( a , b , msg ){ if ( a == b ) return; - if ( ( a != null && b != null ) && - ( /*a.toString() == b.toString() || */a == b || tojson( a ) == tojson( b ) ) ) + if ( ( a != null && b != null ) && friendlyEqual( a , b ) ) return; throw "[" + tojson( a ) + "] != [" + tojson( b ) + "] are not equal : " + msg; @@ -379,20 +389,36 @@ shellHelper.show = function( what ){ } +if ( typeof( Map ) == "undefined" ){ + Map = function(){ + this._data = []; + } +} -Map = function(){ +Map.prototype.put = function( key , value ){ + var o = this._get( key ); + var old = o.value; + o.value = value; + return old; } -Map.prototype.values = function(){ - // TODO: move this to c? - var a = []; - for ( var k in this ){ - var v = this[k]; - if ( v == Map.prototype.values ) - continue; - a.push( v ); +Map.prototype.get = function( key ){ + return this._get( key ).value; +} + +Map.prototype._get = function( key ){ + for ( var i=0; i<this._data.length; i++ ){ + if ( friendlyEqual( key , this._data[i].key ) ){ + return this._data[i]; + } } - return a; + var o = { key : key , value : null }; + this._data.push( o ); + return o; +} + +Map.prototype.values = function(){ + return this._data.map( function(z){ return z.value } ); } Math.sigFig = function( x , N ){ |