23 #include <drizzled/error.h>
24 #include <drizzled/plugin/function.h>
25 #include <drizzled/function/str/strfunc.h>
29 #define JS_ENGINE "v8"
32 using namespace drizzled;
35 namespace drizzle_plugin {
38 v8::Handle<v8::Value> V8Version(
const v8::Arguments& args);
39 v8::Handle<v8::Value> JsEngine(
const v8::Arguments& args);
40 const char* v8_to_char(
const v8::String::Utf8Value& value);
41 void emit_drizzle_error(v8::TryCatch* try_catch);
53 const char *func_name()
const
58 void fix_length_and_dec()
61 max_length= MAX_BLOB_WIDTH;
64 bool check_argument_count(
int n)
76 const char* v8_to_char(
const v8::String::Utf8Value& value) {
77 return *value ? *value :
"<javascript v8 string conversion failed>";
85 void emit_drizzle_error(v8::TryCatch* try_catch)
87 v8::HandleScope handle_scope;
88 v8::String::Utf8Value exception(try_catch->Exception());
89 const char* exception_string = v8_to_char(exception);
90 v8::Handle<v8::Message> message = try_catch->Message();
91 if (message.IsEmpty()) {
94 my_error(ER_SCRIPT, MYF(0), exception_string);
97 int linenum = message->GetLineNumber();
98 sprintf(buf,
"At line %i: %.1900s (Do SHOW ERRORS for more information.)", linenum, exception_string);
99 my_error(ER_SCRIPT, MYF(0), buf);
101 v8::String::Utf8Value sourceline(message->GetSourceLine());
102 const char* sourceline_string = v8_to_char(sourceline);
103 sprintf(buf,
"Line %i: %.160s", linenum, sourceline_string);
104 my_error(ER_SCRIPT, MYF(0), buf);
105 int start = message->GetStartColumn();
106 sprintf(buf,
"Check your script starting at: '%.50s'", &sourceline_string[start]);
107 my_error(ER_SCRIPT, MYF(0), buf);
108 v8::String::Utf8Value stack_trace(try_catch->StackTrace());
109 if (stack_trace.length() > 0) {
110 const char* stack_trace_string = v8_to_char(stack_trace);
111 my_error(ER_SCRIPT, MYF(0), stack_trace_string);
141 assert( fixed == 1 );
147 source_str = args[0]->val_str( str );
156 v8::HandleScope handle_scope;
158 v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
160 v8::Handle<v8::ObjectTemplate> db = v8::ObjectTemplate::New();
161 v8::Handle<v8::ObjectTemplate> js = v8::ObjectTemplate::New();
163 global->Set( v8::String::New(
"db"), db );
164 db->Set( v8::String::New(
"js"), js );
165 js->Set( v8::String::New(
"version"), v8::FunctionTemplate::New(V8Version) );
166 js->Set( v8::String::New(
"engine"), v8::FunctionTemplate::New(JsEngine) );
170 v8::Persistent<v8::Context> context = v8::Context::New( NULL, global );
171 if ( context.IsEmpty() ) {
173 sprintf(buf,
"Error in js() while creating JavaScript context in %s.", JS_ENGINE);
174 my_error(ER_SCRIPT, MYF(0), buf);
179 v8::Handle<v8::Array> a = v8::Array::New(arg_count-1);
180 for( uint64_t n = 1; n < arg_count; n++ )
184 if( args[n]->result_type() == INT_RESULT ){
186 if( args[n]->is_unsigned() ) {
187 a->Set( n-1, v8::Integer::NewFromUnsigned( (uint32_t) args[n]->val_uint() ) );
189 a->Set( n-1, v8::Integer::New((int32_t)args[n]->val_int() ) );
191 }
else if ( args[n]->result_type() == REAL_RESULT || args[n]->result_type() == DECIMAL_RESULT ) {
192 a->Set( n-1, v8::Number::New(args[n]->val_real() ) );
193 }
else if (
true || args[n]->result_type() == STRING_RESULT ) {
194 if ( args[n]->is_datetime() ) {
200 args[n]->get_date(ltime, 0);
214 a->Set( n-1, v8::Date::New(((uint64_t)tmp)*1000) );
216 a->Set( n-1, v8::String::New(args[n]->val_str(str)->c_str() ) );
220 a->Set( n-1, v8::String::New(args[n]->val_str(str)->c_str() ) );
224 if( ! args[n]->is_autogenerated_name ) {
225 if( args[n]->result_type() == INT_RESULT ){
226 if( args[n]->is_unsigned() ) {
227 context->Global()->Set( v8::String::New( args[n]->name ), v8::Integer::NewFromUnsigned( (uint32_t) args[n]->val_uint() ) );
229 context->Global()->Set( v8::String::New( args[n]->name ), v8::Integer::New((int32_t)args[n]->val_int() ) );
231 }
else if ( args[n]->result_type() == REAL_RESULT || args[n]->result_type() == DECIMAL_RESULT ) {
232 context->Global()->Set( v8::String::New( args[n]->name ), v8::Number::New(args[n]->val_real() ) );
233 }
else if (
true || args[n]->result_type() == STRING_RESULT ) {
234 if ( args[n]->is_datetime() ) {
240 args[n]->get_date(ltime, 0);
254 context->Global()->Set( v8::String::New( args[n]->name ), v8::Date::New(((uint64_t)tmp)*1000) );
256 context->Global()->Set( v8::String::New( args[n]->name ), v8::String::New(args[n]->val_str(str)->c_str() ) );
259 context->Global()->Set( v8::String::New( args[n]->name ), v8::String::New(args[n]->val_str(str)->c_str() ) );
265 context->Global()->Set( v8::String::New(
"arguments"), a );
270 v8::TryCatch try_catch;
271 v8::Handle<v8::Value> result;
274 v8::Handle<v8::String> source = v8::String::New(source_str->c_str());
275 v8::Handle<v8::Script> script = v8::Script::Compile(source);
276 if ( script.IsEmpty() ) {
277 emit_drizzle_error(&try_catch);
280 result = script->Run();
281 if ( result.IsEmpty() ) {
282 assert( try_catch.HasCaught() );
283 emit_drizzle_error( &try_catch );
289 assert( !try_catch.HasCaught() );
290 if ( result->IsUndefined() ) {
302 v8::Handle<v8::String> rstring = result->ToString();
307 str->alloc( rstring->Utf8Length() );
309 rstring->WriteUtf8( str->ptr() );
311 str->length( rstring->Utf8Length() );
329 context.add( js_function );
331 v8::V8::Initialize();
342 v8::Handle<v8::Value> V8Version(
const v8::Arguments& ) {
343 return v8::String::New( v8::V8::GetVersion() );
350 v8::Handle<v8::Value> JsEngine(
const v8::Arguments& ) {
351 return v8::String::New( JS_ENGINE );
358 DRIZZLE_DECLARE_PLUGIN
364 N_(
"Executes JavaScript code with supplied arguments"),
366 drizzle_plugin::js::initialize,
370 DRIZZLE_DECLARE_PLUGIN_END;