~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/js_eval/js_eval.cc

  • Committer: Henrik Ingo
  • Date: 2011-09-08 11:37:58 UTC
  • mto: This revision was merged to the branch mainline in revision 2439.
  • Revision ID: henrik.ingo@avoinelama.fi-20110908113758-o8upiz5ox6x5m354
Use my_error() to return v8 errors to the client instead of stdout/log.
Added new error type ER_SCRIPT to error_t.h.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
#include <config.h>
21
21
#include <stdio.h>
22
22
 
 
23
#include <drizzled/error.h>
23
24
#include <drizzled/plugin/function.h>
24
25
#include <drizzled/function/str/strfunc.h>
25
26
 
92
93
  if (message.IsEmpty()) {
93
94
    // V8 didn't provide any extra information about this error; just
94
95
    // print the exception.
95
 
    printf("%s\n", exception_string);
 
96
    my_error(ER_SCRIPT, MYF(0), exception_string);
96
97
  } else {
97
 
    // Print (filename):(line number): (message).
98
 
    v8::String::Utf8Value filename(message->GetScriptResourceName());
99
 
    const char* filename_string = ToCString(filename);
 
98
    char buf[2048]; // TODO: magic number. I'm sure this will crash if you supply a line of javascript longer than 2048.
100
99
    int linenum = message->GetLineNumber();
101
 
    printf("%s:%i: %s\n", filename_string, linenum, exception_string);
 
100
    sprintf(buf, "At line %i: %s (Do SHOW ERRORS for more information.)", linenum, exception_string);
 
101
    my_error(ER_SCRIPT, MYF(0), buf);
102
102
    // Print line of source code.
103
103
    v8::String::Utf8Value sourceline(message->GetSourceLine());
104
104
    const char* sourceline_string = ToCString(sourceline);
105
 
    printf("%s\n", sourceline_string);
106
 
    // Print wavy underline (GetUnderline is deprecated).
 
105
    sprintf(buf, "Line %i: %s", linenum, sourceline_string);
 
106
    my_error(ER_SCRIPT, MYF(0), buf);    
107
107
    int start = message->GetStartColumn();
108
 
    for (int i = 0; i < start; i++) {
109
 
      printf(" ");
110
 
    }
111
 
    int end = message->GetEndColumn();
112
 
    for (int i = start; i < end; i++) {
113
 
      printf("^");
114
 
    }
115
 
    printf("\n");
 
108
    sprintf(buf, "Check your script starting at: '%.50s'", &sourceline_string[start]);
 
109
    my_error(ER_SCRIPT, MYF(0), buf);
116
110
    v8::String::Utf8Value stack_trace(try_catch->StackTrace());
117
111
    if (stack_trace.length() > 0) {
118
112
      const char* stack_trace_string = ToCString(stack_trace);
119
 
      printf("%s\n", stack_trace_string);
 
113
      my_error(ER_SCRIPT, MYF(0), stack_trace_string);
120
114
    }
121
115
  }
122
116
}
126
120
 * 
127
121
 * @note I only compiled this with -O0 but should work with default O2 also.
128
122
 *
129
 
 * @todo Accepts more than one parameter, but doesn't use them.
130
 
 * @todo How does it work if I want to return integers and doubles?
 
123
 * @todo datetime and row_result types are not yet handled
131
124
 * @todo v8 exceptions are printed to the log. Should be converted to 
132
125
 * drizzle warning/error and returned with result.
133
126
 * @todo Probably the v8 stuff will be moved to it's own function in the future.
 
127
 * @todo Some of the v8 stuff should be done in initialize()
134
128
 * @todo Documentation for drizzle manual in .rst format
135
 
 * @todo When available, use v8::Isolate instead of v8::Locker for multithreading
 
129
 * @todo When available, use v8::Isolate instead of v8::Locker for multithreading (or a mix of both)
 
130
 * 
 
131
 * @note DECIMAL_RESULT type is now a double in JavaScript. This could lose precision.
 
132
 * But to send them as strings would also be awkward (+ operator will do unexpected things).
 
133
 * In any case, we'd need some biginteger (bigdecimal?) kind of library to do anything with higher
 
134
 * precision values anyway. If you want to keep the precision, you can cast your
 
135
 * decimal values to strings explicitly when passing them as arguments.
136
136
 * 
137
137
 * @param res Pointer to the drizzled::String object that will contain the result
138
138
 * @return a drizzled::String containing the value returned by executed JavaScript code (value of last executed statement) 
147
147
  String *source_str=NULL;
148
148
  source_str = args[0]->val_str( str ); 
149
149
  
150
 
  // TODO Some of this (ObjectTemplate bindings) should probably be 
151
 
  // moved to initialize, but then it must be allocated on the heap.
152
 
  
153
150
  // Need to use Locker in multi-threaded app. v8 is unlocked by the destructor 
154
151
  // when locker goes out of scope.
155
152
  // TODO: Newer versions of v8 provide an Isolate class where you can get a 
173
170
  // v8::Array can only be created when context is already entered (otherwise v8 segfaults!)
174
171
  v8::Persistent<v8::Context> context = v8::Context::New( NULL, global );
175
172
  if ( context.IsEmpty() ) {
176
 
    // TODO: how do I set warning/error in the drizzle result?
177
 
    printf( "Error in js_eval() while creating JavaScript context in v8.\n" );
 
173
    char buf[100];
 
174
    sprintf(buf, "Error in js_eval() while creating JavaScript context in %s.", JS_ENGINE);
 
175
    my_error(ER_SCRIPT, MYF(0), buf);
178
176
    return NULL;
179
177
  }
180
178
  context->Enter();
183
181
  for( uint64_t n = 1; n < arg_count; n++ )
184
182
  {
185
183
    // Need to do this differently for ints, doubles and strings
 
184
    // TODO: Should also handle dates. See is_datetime() in drizzled/item.h.
186
185
    // TODO: There is also ROW_RESULT. Is that relevant here? What does it look like? I could pass rows as an array or object.
187
186
    if( args[n]->result_type() == INT_RESULT ){
188
187
      if( args[n]->is_unsigned() ) {
192
191
      }
193
192
    } else if ( args[n]->result_type() == REAL_RESULT || args[n]->result_type() == DECIMAL_RESULT ) {
194
193
      a->Set( n-1, v8::Number::New(args[n]->val_real() ) );
195
 
    // TODO: Here's a question: Should DECIMAL_RESULT be sent as double or string?
196
 
    // Kind of unusable either way, we'd need to bind some biginteger arithmetic library into the js environment to make them usable
197
194
    } else if ( true || args[n]->result_type() == STRING_RESULT ) {
198
195
      // Default to creating string values in JavaScript
199
196
      a->Set( n-1, v8::String::New(args[n]->val_str(str)->c_str() ) );
226
223
  v8::Handle<v8::String> source = v8::String::New(source_str->c_str());
227
224
  v8::Handle<v8::Script> script = v8::Script::Compile(source);
228
225
  if ( script.IsEmpty() ) {
229
 
    // TODO: how do I set warning/error in the drizzle result?
230
 
    // Print errors that happened during compilation.
231
226
    ReportException(&try_catch);
232
227
    return NULL;
233
228
  } else {
234
229
    result = script->Run();
235
230
    if ( result.IsEmpty() ) {
236
231
      assert( try_catch.HasCaught() );
237
 
      // TODO: how do I set warning/error in the drizzle result?
238
 
      // Print errors that happened during execution.
239
232
      ReportException( &try_catch );
240
233
      // Dispose of Persistent objects before returning. (Is it needed?)
241
234
      context->Exit();