summaryrefslogtreecommitdiff
path: root/scripting/v8_db.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scripting/v8_db.cpp')
-rw-r--r--scripting/v8_db.cpp210
1 files changed, 187 insertions, 23 deletions
diff --git a/scripting/v8_db.cpp b/scripting/v8_db.cpp
index 6d859d4..4d14a03 100644
--- a/scripting/v8_db.cpp
+++ b/scripting/v8_db.cpp
@@ -19,7 +19,8 @@
#include "v8_utils.h"
#include "v8_db.h"
#include "engine.h"
-
+#include "util/base64.h"
+#include "../client/syncclusterconnection.h"
#include <iostream>
using namespace std;
@@ -49,6 +50,26 @@ namespace mongo {
return mongo;
}
+ v8::Handle<v8::FunctionTemplate> getNumberLongFunctionTemplate() {
+ v8::Local<v8::FunctionTemplate> numberLong = FunctionTemplate::New( numberLongInit );
+ v8::Local<v8::Template> proto = numberLong->PrototypeTemplate();
+
+ proto->Set( v8::String::New( "valueOf" ) , FunctionTemplate::New( numberLongValueOf ) );
+ proto->Set( v8::String::New( "toNumber" ) , FunctionTemplate::New( numberLongToNumber ) );
+ proto->Set( v8::String::New( "toString" ) , FunctionTemplate::New( numberLongToString ) );
+
+ return numberLong;
+ }
+
+ v8::Handle<v8::FunctionTemplate> getBinDataFunctionTemplate() {
+ v8::Local<v8::FunctionTemplate> binData = FunctionTemplate::New( binDataInit );
+ v8::Local<v8::Template> proto = binData->PrototypeTemplate();
+
+ proto->Set( v8::String::New( "toString" ) , FunctionTemplate::New( binDataToString ) );
+
+ return binData;
+ }
+
void installDBTypes( Handle<ObjectTemplate>& global ){
v8::Local<v8::FunctionTemplate> db = FunctionTemplate::New( dbInit );
db->InstanceTemplate()->SetNamedPropertyHandler( collectionFallback );
@@ -69,7 +90,9 @@ namespace mongo {
global->Set( v8::String::New("DBPointer") , FunctionTemplate::New( dbPointerInit ) );
- global->Set( v8::String::New("BinData") , FunctionTemplate::New( binDataInit ) );
+ global->Set( v8::String::New("BinData") , getBinDataFunctionTemplate() );
+
+ global->Set( v8::String::New("NumberLong") , getNumberLongFunctionTemplate() );
}
@@ -93,7 +116,9 @@ namespace mongo {
global->Set( v8::String::New("DBPointer") , FunctionTemplate::New( dbPointerInit )->GetFunction() );
- global->Set( v8::String::New("BinData") , FunctionTemplate::New( binDataInit )->GetFunction() );
+ global->Set( v8::String::New("BinData") , getBinDataFunctionTemplate()->GetFunction() );
+
+ global->Set( v8::String::New("NumberLong") , getNumberLongFunctionTemplate()->GetFunction() );
BSONObjBuilder b;
b.appendMaxKey( "" );
@@ -107,7 +132,8 @@ namespace mongo {
}
void destroyConnection( Persistent<Value> object, void* parameter){
- cout << "Yo ho ho" << endl;
+ // TODO
+ cout << "warning: destroyConnection not implemented" << endl;
}
Handle<Value> mongoConsExternal(const Arguments& args){
@@ -122,16 +148,45 @@ namespace mongo {
strcpy( host , "127.0.0.1" );
}
- DBClientConnection * conn = new DBClientConnection( true );
-
+ DBClientWithCommands * conn = 0;
+ int commas = 0;
+ for ( int i=0; i<255; i++ ){
+ if ( host[i] == ',' )
+ commas++;
+ else if ( host[i] == 0 )
+ break;
+ }
+
+ if ( commas == 0 ){
+ DBClientConnection * c = new DBClientConnection( true );
+ string errmsg;
+ if ( ! c->connect( host , errmsg ) ){
+ delete c;
+ string x = "couldn't connect: ";
+ x += errmsg;
+ return v8::ThrowException( v8::String::New( x.c_str() ) );
+ }
+ conn = c;
+ }
+ else if ( commas == 1 ){
+ DBClientPaired * c = new DBClientPaired();
+ if ( ! c->connect( host ) ){
+ delete c;
+ return v8::ThrowException( v8::String::New( "couldn't connect to pair" ) );
+ }
+ conn = c;
+ }
+ else if ( commas == 2 ){
+ conn = new SyncClusterConnection( host );
+ }
+ else {
+ return v8::ThrowException( v8::String::New( "too many commas" ) );
+ }
+
Persistent<v8::Object> self = Persistent<v8::Object>::New( args.This() );
self.MakeWeak( conn , destroyConnection );
- string errmsg;
- if ( ! conn->connect( host , errmsg ) ){
- return v8::ThrowException( v8::String::New( "couldn't connect" ) );
- }
-
+ ScriptEngine::runConnectCallback( *conn );
// NOTE I don't believe the conn object will ever be freed.
args.This()->Set( CONN_STRING , External::New( conn ) );
args.This()->Set( v8::String::New( "slaveOk" ) , Boolean::New( false ) );
@@ -184,7 +239,7 @@ namespace mongo {
4 - skip
*/
Handle<Value> mongoFind(const Arguments& args){
- jsassert( args.Length() == 5 , "find needs 5 args" );
+ jsassert( args.Length() == 6 , "find needs 6 args" );
jsassert( args[1]->IsObject() , "needs to be an object" );
DBClientBase * conn = getConnection( args );
GETNS;
@@ -201,14 +256,15 @@ namespace mongo {
Local<v8::Value> slaveOkVal = mongo->Get( v8::String::New( "slaveOk" ) );
jsassert( slaveOkVal->IsBoolean(), "slaveOk member invalid" );
bool slaveOk = slaveOkVal->BooleanValue();
-
+
try {
auto_ptr<mongo::DBClientCursor> cursor;
int nToReturn = (int)(args[3]->ToNumber()->Value());
int nToSkip = (int)(args[4]->ToNumber()->Value());
+ int batchSize = (int)(args[5]->ToNumber()->Value());
{
v8::Unlocker u;
- cursor = conn->query( ns, q , nToReturn , nToSkip , haveFields ? &fields : 0, slaveOk ? QueryOption_SlaveOk : 0 );
+ cursor = conn->query( ns, q , nToReturn , nToSkip , haveFields ? &fields : 0, slaveOk ? QueryOption_SlaveOk : 0 , batchSize );
}
v8::Function * cons = (v8::Function*)( *( mongo->Get( v8::String::New( "internalCursor" ) ) ) );
assert( cons );
@@ -399,6 +455,11 @@ namespace mongo {
t->Set( v8::String::New( "_skip" ) , args[7] );
else
t->Set( v8::String::New( "_skip" ) , Number::New( 0 ) );
+
+ if ( args.Length() > 8 && args[8]->IsNumber() )
+ t->Set( v8::String::New( "_batchSize" ) , args[7] );
+ else
+ t->Set( v8::String::New( "_batchSize" ) , Number::New( 0 ) );
t->Set( v8::String::New( "_cursor" ) , v8::Null() );
t->Set( v8::String::New( "_numReturned" ) , v8::Number::New(0) );
@@ -473,7 +534,7 @@ namespace mongo {
v8::Handle<v8::Value> dbRefInit( const v8::Arguments& args ) {
- if (args.Length() != 2) {
+ if (args.Length() != 2 && args.Length() != 0) {
return v8::ThrowException( v8::String::New( "DBRef needs 2 arguments" ) );
}
@@ -484,8 +545,10 @@ namespace mongo {
it = f->NewInstance();
}
- it->Set( v8::String::New( "$ref" ) , args[0] );
- it->Set( v8::String::New( "$id" ) , args[1] );
+ if ( args.Length() == 2 ) {
+ it->Set( v8::String::New( "$ref" ) , args[0] );
+ it->Set( v8::String::New( "$id" ) , args[1] );
+ }
return it;
}
@@ -511,25 +574,126 @@ namespace mongo {
}
v8::Handle<v8::Value> binDataInit( const v8::Arguments& args ) {
+ v8::Handle<v8::Object> it = args.This();
+
+ // 3 args: len, type, data
+ if (args.Length() == 3) {
- if (args.Length() != 3) {
+ if ( it->IsUndefined() || it == v8::Context::GetCurrent()->Global() ){
+ v8::Function* f = getNamedCons( "BinData" );
+ it = f->NewInstance();
+ }
+
+ it->Set( v8::String::New( "len" ) , args[0] );
+ it->Set( v8::String::New( "type" ) , args[1] );
+ it->Set( v8::String::New( "data" ), args[2] );
+ it->SetHiddenValue( v8::String::New( "__BinData" ), v8::Number::New( 1 ) );
+
+ // 2 args: type, base64 string
+ } else if ( args.Length() == 2 ) {
+
+ if ( it->IsUndefined() || it == v8::Context::GetCurrent()->Global() ){
+ v8::Function* f = getNamedCons( "BinData" );
+ it = f->NewInstance();
+ }
+
+ v8::String::Utf8Value data( args[ 1 ] );
+ string decoded = base64::decode( *data );
+ it->Set( v8::String::New( "len" ) , v8::Number::New( decoded.length() ) );
+ it->Set( v8::String::New( "type" ) , args[ 0 ] );
+ it->Set( v8::String::New( "data" ), v8::String::New( decoded.data(), decoded.length() ) );
+ it->SetHiddenValue( v8::String::New( "__BinData" ), v8::Number::New( 1 ) );
+
+ } else {
return v8::ThrowException( v8::String::New( "BinData needs 3 arguments" ) );
}
+
+ return it;
+ }
+
+ v8::Handle<v8::Value> binDataToString( const v8::Arguments& args ) {
+
+ if (args.Length() != 0) {
+ return v8::ThrowException( v8::String::New( "toString needs 0 arguments" ) );
+ }
+
+ v8::Handle<v8::Object> it = args.This();
+ int len = it->Get( v8::String::New( "len" ) )->ToInt32()->Value();
+ int type = it->Get( v8::String::New( "type" ) )->ToInt32()->Value();
+ v8::String::Utf8Value data( it->Get( v8::String::New( "data" ) ) );
+
+ stringstream ss;
+ ss << "BinData( type: " << type << ", base64: \"";
+ base64::encode( ss, *data, len );
+ ss << "\" )";
+ string ret = ss.str();
+ return v8::String::New( ret.c_str() );
+ }
+
+ v8::Handle<v8::Value> numberLongInit( const v8::Arguments& args ) {
+
+ if (args.Length() != 1 && args.Length() != 3) {
+ return v8::ThrowException( v8::String::New( "NumberLong needs 1 or 3 arguments" ) );
+ }
v8::Handle<v8::Object> it = args.This();
if ( it->IsUndefined() || it == v8::Context::GetCurrent()->Global() ){
- v8::Function* f = getNamedCons( "BinData" );
+ v8::Function* f = getNamedCons( "NumberLong" );
it = f->NewInstance();
}
- it->Set( v8::String::New( "len" ) , args[0] );
- it->Set( v8::String::New( "type" ) , args[1] );
- it->Set( v8::String::New( "data" ), args[2] );
- it->SetHiddenValue( v8::String::New( "__BinData" ), v8::Number::New( 1 ) );
+ it->Set( v8::String::New( "floatApprox" ) , args[0] );
+ if ( args.Length() == 3 ) {
+ it->Set( v8::String::New( "top" ) , args[1] );
+ it->Set( v8::String::New( "bottom" ) , args[2] );
+ }
+ it->SetHiddenValue( v8::String::New( "__NumberLong" ), v8::Number::New( 1 ) );
return it;
}
+
+ long long numberLongVal( const v8::Handle< v8::Object > &it ) {
+ if ( !it->Has( v8::String::New( "top" ) ) )
+ return (long long)( it->Get( v8::String::New( "floatApprox" ) )->NumberValue() );
+ return
+ (long long)
+ ( (unsigned long long)( it->Get( v8::String::New( "top" ) )->ToInt32()->Value() ) << 32 ) +
+ (unsigned)( it->Get( v8::String::New( "bottom" ) )->ToInt32()->Value() );
+ }
+
+ v8::Handle<v8::Value> numberLongValueOf( const v8::Arguments& args ) {
+
+ if (args.Length() != 0) {
+ return v8::ThrowException( v8::String::New( "toNumber needs 0 arguments" ) );
+ }
+
+ v8::Handle<v8::Object> it = args.This();
+
+ long long val = numberLongVal( it );
+
+ return v8::Number::New( double( val ) );
+ }
+
+ v8::Handle<v8::Value> numberLongToNumber( const v8::Arguments& args ) {
+ return numberLongValueOf( args );
+ }
+
+ v8::Handle<v8::Value> numberLongToString( const v8::Arguments& args ) {
+
+ if (args.Length() != 0) {
+ return v8::ThrowException( v8::String::New( "toString needs 0 arguments" ) );
+ }
+
+ v8::Handle<v8::Object> it = args.This();
+
+ long long val = numberLongVal( it );
+
+ stringstream ss;
+ ss << val;
+ string ret = ss.str();
+ return v8::String::New( ret.c_str() );
+ }
v8::Handle<v8::Value> bsonsize( const v8::Arguments& args ) {