summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEliot Horowitz <eliot@10gen.com>2009-06-08 10:54:55 -0400
committerEliot Horowitz <eliot@10gen.com>2009-06-08 10:54:55 -0400
commitd5122c9b90ef1f45585e09c45610488ff76894cf (patch)
tree594907f6b0c1283cae0b45d50a3f2425ab8f7399
parentb6e455fd69c2cb9d2bb12b39c8cc721f2e5c3f61 (diff)
downloadmongo-d5122c9b90ef1f45585e09c45610488ff76894cf.tar.gz
change Map to use Map.get Map.put Map[] won't work
more tests for group
-rw-r--r--jstests/group1.js17
-rw-r--r--jstests/map1.js23
-rw-r--r--scripting/sm_db.cpp44
-rw-r--r--shell/db.js10
-rw-r--r--shell/utils.js50
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 , &timestamp_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 ){