diff options
author | Antonin Kral <a.kral@bobek.cz> | 2010-08-11 12:38:57 +0200 |
---|---|---|
committer | Antonin Kral <a.kral@bobek.cz> | 2010-08-11 12:38:57 +0200 |
commit | 7645618fd3914cb8a20561625913c20d49504a49 (patch) | |
tree | 8370f846f58f6d71165b7a0e2eda04648584ec76 /scripting/sm_db.cpp | |
parent | 68c73c3c7608b4c87f07440dc3232801720b1168 (diff) | |
download | mongodb-7645618fd3914cb8a20561625913c20d49504a49.tar.gz |
Imported Upstream version 1.6.0
Diffstat (limited to 'scripting/sm_db.cpp')
-rw-r--r-- | scripting/sm_db.cpp | 254 |
1 files changed, 205 insertions, 49 deletions
diff --git a/scripting/sm_db.cpp b/scripting/sm_db.cpp index 1c15170..855a50d 100644 --- a/scripting/sm_db.cpp +++ b/scripting/sm_db.cpp @@ -19,6 +19,15 @@ #include "../client/syncclusterconnection.h" #include "../util/base64.h" +#include "../util/text.h" +#include "../util/hex.h" + +#if( BOOST_VERSION >= 104200 ) +//#include <boost/uuid/uuid.hpp> +#define HAVE_UUID 1 +#else +; +#endif namespace mongo { @@ -90,6 +99,13 @@ namespace mongo { return JS_TRUE; } + JSBool internal_cursor_objsLeftInBatch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ + DBClientCursor *cursor = getCursor( cx, obj ); + Convertor c(cx); + *rval = c.toval((double) cursor->objsLeftInBatch() ); + return JS_TRUE; + } + JSBool internal_cursor_next(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ DBClientCursor *cursor = getCursor( cx, obj ); if ( ! cursor->more() ){ @@ -105,6 +121,7 @@ namespace mongo { JSFunctionSpec internal_cursor_functions[] = { { "hasNext" , internal_cursor_hasNext , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } , + { "objsLeftInBatch" , internal_cursor_objsLeftInBatch , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } , { "next" , internal_cursor_next , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } , { 0 } }; @@ -145,37 +162,22 @@ namespace mongo { if ( argc > 0 ) host = c.toString( argv[0] ); - int numCommas = DBClientBase::countCommas( host ); - - shared_ptr< DBClientWithCommands > conn; - string errmsg; - if ( numCommas == 0 ){ - DBClientConnection * c = new DBClientConnection( true ); - conn.reset( c ); - if ( ! c->connect( host , errmsg ) ){ - JS_ReportError( cx , ((string)"couldn't connect: " + errmsg).c_str() ); - return JS_FALSE; - } - ScriptEngine::runConnectCallback( *c ); - } - else if ( numCommas == 1 ){ // paired - DBClientPaired * c = new DBClientPaired(); - conn.reset( c ); - if ( ! c->connect( host ) ){ - JS_ReportError( cx , "couldn't connect to pair" ); - return JS_FALSE; - } - } - else if ( numCommas == 2 ){ - conn.reset( new SyncClusterConnection( host ) ); + + ConnectionString cs = ConnectionString::parse( host , errmsg ); + if ( ! cs.isValid() ){ + JS_ReportError( cx , errmsg.c_str() ); + return JS_FALSE; } - else { - JS_ReportError( cx , "1 (paired) or 2(quorum) commas are allowed" ); + + shared_ptr< DBClientWithCommands > conn( cs.connect( errmsg ) ); + if ( ! conn ){ + JS_ReportError( cx , errmsg.c_str() ); return JS_FALSE; } - + ScriptEngine::runConnectCallback( *conn ); + assert( JS_SetPrivate( cx , obj , (void*)( new shared_ptr< DBClientWithCommands >( conn ) ) ) ); jsval host_val = c.toval( host.c_str() ); assert( JS_SetProperty( cx , obj , "host" , &host_val ) ); @@ -342,7 +344,6 @@ namespace mongo { { 0 } }; - // ------------- db_collection ------------- JSBool db_collection_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){ @@ -516,7 +517,7 @@ namespace mongo { JSBool object_id_tostring(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ Convertor c(cx); - return *rval = c.getProperty( obj , "str" ); + return (JSBool) (*rval = c.getProperty( obj , "str" )); } JSFunctionSpec object_id_functions[] = { @@ -524,7 +525,6 @@ namespace mongo { { 0 } }; - // dbpointer JSBool dbpointer_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){ @@ -580,8 +580,78 @@ namespace mongo { JSClass dbref_class = bson_class; // name will be fixed later - // BinData + // UUID ************************** + + JSBool uuid_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){ + Convertor c( cx ); + + if( argc == 0 ) { +#if defined(HAVE_UUID) + //uuids::uuid +#else +#endif + JS_ReportError( cx , "UUID needs 1 argument -- UUID(hexstr)" ); + return JS_FALSE; + } + else if ( argc == 1 ) { + + string encoded = c.toString( argv[ 0 ] ); + if( encoded.size() != 32 ) { + JS_ReportError( cx, "expect 32 char hex string to UUID()" ); + return JS_FALSE; + } + + char buf[16]; + for( int i = 0; i < 16; i++ ) { + buf[i] = fromHex(encoded.c_str() + i * 2); + } + + assert( JS_SetPrivate( cx, obj, new BinDataHolder( buf, 16 ) ) ); + c.setProperty( obj, "len", c.toval( (double)16 ) ); + c.setProperty( obj, "type", c.toval( (double)3 ) ); + + return JS_TRUE; + } + else { + JS_ReportError( cx , "UUID needs 1 argument -- UUID(hexstr)" ); + return JS_FALSE; + } + } + + JSBool uuid_tostring(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ + Convertor c(cx); + void *holder = JS_GetPrivate( cx, obj ); + assert( holder ); + const char *data = ( ( BinDataHolder* )( holder ) )->c_; + stringstream ss; + ss << "UUID(\"" << toHex(data, 16); + ss << "\")"; + string ret = ss.str(); + return *rval = c.toval( ret.c_str() ); + } + + void uuid_finalize( JSContext * cx , JSObject * obj ){ + Convertor c(cx); + void *holder = JS_GetPrivate( cx, obj ); + if ( holder ){ + delete ( BinDataHolder* )holder; + assert( JS_SetPrivate( cx , obj , 0 ) ); + } + } + + JSClass uuid_class = { + "UUID" , JSCLASS_HAS_PRIVATE , + JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, + JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, uuid_finalize, + JSCLASS_NO_OPTIONAL_MEMBERS + }; + JSFunctionSpec uuid_functions[] = { + { "toString" , uuid_tostring , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } , + { 0 } + }; + + // BinData ************************** JSBool bindata_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){ Convertor c( cx ); @@ -589,17 +659,28 @@ namespace mongo { if ( argc == 2 ){ int type = (int)c.toNumber( argv[ 0 ] ); + if( type < 0 || type > 255 ) { + JS_ReportError( cx , "invalid BinData subtype -- range is 0..255 see bsonspec.org" ); + return JS_FALSE; + } string encoded = c.toString( argv[ 1 ] ); - string decoded = base64::decode( encoded ); + string decoded; + try { + decoded = base64::decode( encoded ); + } + catch(...) { + JS_ReportError(cx, "BinData could not decode base64 parameter"); + return JS_FALSE; + } assert( JS_SetPrivate( cx, obj, new BinDataHolder( decoded.data(), decoded.length() ) ) ); - c.setProperty( obj, "len", c.toval( decoded.length() ) ); - c.setProperty( obj, "type", c.toval( type ) ); + c.setProperty( obj, "len", c.toval( (double)decoded.length() ) ); + c.setProperty( obj, "type", c.toval( (double)type ) ); return JS_TRUE; } else { - JS_ReportError( cx , "BinData needs 2 arguments" ); + JS_ReportError( cx , "BinData needs 2 arguments -- BinData(subtype,data)" ); return JS_FALSE; } } @@ -612,13 +693,53 @@ namespace mongo { assert( holder ); const char *data = ( ( BinDataHolder* )( holder ) )->c_; stringstream ss; - ss << "BinData( type: " << type << ", base64: \""; + ss << "BinData(" << type << ",\""; base64::encode( ss, (const char *)data, len ); - ss << "\" )"; + ss << "\")"; + string ret = ss.str(); + return *rval = c.toval( ret.c_str() ); + } + + JSBool bindataBase64(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ + Convertor c(cx); + int len = (int)c.getNumber( obj, "len" ); + void *holder = JS_GetPrivate( cx, obj ); + assert( holder ); + const char *data = ( ( BinDataHolder* )( holder ) )->c_; + stringstream ss; + base64::encode( ss, (const char *)data, len ); + string ret = ss.str(); + return *rval = c.toval( ret.c_str() ); + } + + JSBool bindataAsHex(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ + Convertor c(cx); + int len = (int)c.getNumber( obj, "len" ); + void *holder = JS_GetPrivate( cx, obj ); + assert( holder ); + const char *data = ( ( BinDataHolder* )( holder ) )->c_; + stringstream ss; + ss << hex; + for( int i = 0; i < len; i++ ) { + unsigned v = (unsigned char) data[i]; + ss << v; + } string ret = ss.str(); return *rval = c.toval( ret.c_str() ); } + JSBool bindataLength(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ + Convertor c(cx); + int len = (int)c.getNumber( obj, "len" ); + return *rval = c.toval((double) len); + } + + JSBool bindataSubtype(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ + Convertor c(cx); + int t = (int)c.getNumber( obj, "type" ); + return *rval = c.toval((double) t); + } + void bindata_finalize( JSContext * cx , JSObject * obj ){ Convertor c(cx); void *holder = JS_GetPrivate( cx, obj ); @@ -637,6 +758,10 @@ namespace mongo { JSFunctionSpec bindata_functions[] = { { "toString" , bindata_tostring , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } , + { "hex", bindataAsHex, 0, JSPROP_READONLY | JSPROP_PERMANENT, 0 } , + { "base64", bindataBase64, 0, JSPROP_READONLY | JSPROP_PERMANENT, 0 } , + { "length", bindataLength, 0, JSPROP_READONLY | JSPROP_PERMANENT, 0 } , + { "subtype", bindataSubtype, 0, JSPROP_READONLY | JSPROP_PERMANENT, 0 } , { 0 } }; @@ -699,6 +824,31 @@ namespace mongo { JSCLASS_NO_OPTIONAL_MEMBERS }; + JSBool numberlong_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){ + smuassert( cx , "NumberLong needs 0 or 1 args" , argc == 0 || argc == 1 ); + + Convertor c( cx ); + if ( argc == 0 ) { + c.setProperty( obj, "floatApprox", c.toval( 0.0 ) ); + } else if ( JSVAL_IS_NUMBER( argv[ 0 ] ) ) { + c.setProperty( obj, "floatApprox", argv[ 0 ] ); + } else { + string num = c.toString( argv[ 0 ] ); + //PRINT(num); + const char *numStr = num.c_str(); + long long n; + try { + n = parseLL( numStr ); + //PRINT(n); + } catch ( const AssertionException & ) { + smuassert( cx , "could not convert string to long long" , false ); + } + c.makeLongObj( n, obj ); + } + + return JS_TRUE; + } + JSBool numberlong_valueof(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ Convertor c(cx); return *rval = c.toval( double( c.toNumberLongUnsafe( obj ) ) ); @@ -711,7 +861,12 @@ namespace mongo { JSBool numberlong_tostring(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ Convertor c(cx); stringstream ss; - ss << c.toNumberLongUnsafe( obj ); + if ( c.hasProperty( obj, "top" ) ) { + long long val = c.toNumberLongUnsafe( obj ); + ss << "NumberLong( \"" << val << "\" )"; + } else { + ss << "NumberLong( " << c.getNumber( obj, "floatApprox" ) << " )"; + } string ret = ss.str(); return *rval = c.toval( ret.c_str() ); } @@ -819,9 +974,10 @@ namespace mongo { assert( JS_InitClass( cx , global , 0 , &dbquery_class , dbquery_constructor , 0 , 0 , 0 , 0 , 0 ) ); assert( JS_InitClass( cx , global , 0 , &dbpointer_class , dbpointer_constructor , 0 , 0 , dbpointer_functions , 0 , 0 ) ); assert( JS_InitClass( cx , global , 0 , &bindata_class , bindata_constructor , 0 , 0 , bindata_functions , 0 , 0 ) ); + assert( JS_InitClass( cx , global , 0 , &uuid_class , uuid_constructor , 0 , 0 , uuid_functions , 0 , 0 ) ); assert( JS_InitClass( cx , global , 0 , ×tamp_class , 0 , 0 , 0 , 0 , 0 , 0 ) ); - assert( JS_InitClass( cx , global , 0 , &numberlong_class , 0 , 0 , 0 , numberlong_functions , 0 , 0 ) ); + assert( JS_InitClass( cx , global , 0 , &numberlong_class , numberlong_constructor , 0 , 0 , numberlong_functions , 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 ) ); @@ -842,39 +998,39 @@ namespace mongo { if ( JS_InstanceOf( c->_context , o , &object_id_class , 0 ) ){ OID oid; oid.init( c->getString( o , "str" ) ); - b.append( name.c_str() , oid ); + b.append( name , oid ); return true; } if ( JS_InstanceOf( c->_context , o , &minkey_class , 0 ) ){ - b.appendMinKey( name.c_str() ); + b.appendMinKey( name ); return true; } if ( JS_InstanceOf( c->_context , o , &maxkey_class , 0 ) ){ - b.appendMaxKey( name.c_str() ); + b.appendMaxKey( name ); return true; } if ( JS_InstanceOf( c->_context , o , ×tamp_class , 0 ) ){ - b.appendTimestamp( name.c_str() , (unsigned long long)c->getNumber( o , "t" ) , (unsigned int )c->getNumber( o , "i" ) ); + b.appendTimestamp( name , (unsigned long long)c->getNumber( o , "t" ) , (unsigned int )c->getNumber( o , "i" ) ); return true; } if ( JS_InstanceOf( c->_context , o , &numberlong_class , 0 ) ){ - b.append( name.c_str() , c->toNumberLongUnsafe( o ) ); + b.append( name , c->toNumberLongUnsafe( o ) ); return true; } if ( JS_InstanceOf( c->_context , o , &dbpointer_class , 0 ) ){ - b.appendDBRef( name.c_str() , c->getString( o , "ns" ).c_str() , c->toOID( c->getProperty( o , "id" ) ) ); + b.appendDBRef( name , c->getString( o , "ns" ).c_str() , c->toOID( c->getProperty( o , "id" ) ) ); return true; } if ( JS_InstanceOf( c->_context , o , &bindata_class , 0 ) ){ void *holder = JS_GetPrivate( c->_context , o ); const char *data = ( ( BinDataHolder * )( holder ) )->c_; - b.appendBinData( name.c_str() , + b.appendBinData( name , (int)(c->getNumber( o , "len" )) , (BinDataType)((char)(c->getNumber( o , "type" ) ) ) , data ); @@ -886,21 +1042,21 @@ namespace mongo { { jsdouble d = js_DateGetMsecSinceEpoch( c->_context , o ); if ( d ){ - b.appendDate( name.c_str() , Date_t(d) ); + b.appendDate( name , Date_t(d) ); return true; } } #elif defined( XULRUNNER ) if ( JS_InstanceOf( c->_context , o, globalSMEngine->_dateClass , 0 ) ){ jsdouble d = js_DateGetMsecSinceEpoch( c->_context , o ); - b.appendDate( name.c_str() , Date_t(d) ); + b.appendDate( name , Date_t(d) ); return true; } #else if ( JS_InstanceOf( c->_context , o, &js_DateClass , 0 ) ){ jsdouble d = js_DateGetMsecSinceEpoch( c->_context , o ); //TODO: make signed - b.appendDate( name.c_str() , Date_t((unsigned long long)d) ); + b.appendDate( name , Date_t((unsigned long long)d) ); return true; } #endif @@ -909,7 +1065,7 @@ namespace mongo { if ( JS_InstanceOf( c->_context , o , &dbquery_class , 0 ) || JS_InstanceOf( c->_context , o , &mongo_class , 0 ) || JS_InstanceOf( c->_context , o , &db_collection_class , 0 ) ){ - b.append( name.c_str() , c->toString( val ) ); + b.append( name , c->toString( val ) ); return true; } |