Skip to content

Commit cb40945

Browse files
committed
+ require
1 parent 6623f71 commit cb40945

File tree

6 files changed

+143
-37
lines changed

6 files changed

+143
-37
lines changed

Makefile

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
1-
#MYSQL_SRC = -I/data/home/mysql-5.1.56/include -I/data/home/mysql-5.1.56/regex -I/data/home/mysql-5.1.56/sql
1+
MYSQL_SRC = -I/data/home/mysql-5.1.56/include -I/data/home/mysql-5.1.56/regex -I/data/home/mysql-5.1.56/sql
22
V8_LIB = -L/data/home/v8-3.2.10.15 -lv8
33

44
all:
5-
g++ -O0 -ggdb -shared -o udf_example.so udf_example.cpp -I/usr/include/mysql $(V8_LIB) --std=c++0x $(MYSQL_SRC)
5+
g++ -O0 -ggdb -shared -o mysql-js.so mysql-js.cpp -I/usr/include/mysql $(V8_LIB) --std=c++0x $(MYSQL_SRC)
66

77
install:
8-
cp udf_example.so /usr/lib/mysql/plugin/
8+
mysql test_udf -e 'DROP FUNCTION IF EXISTS execute_js'
9+
cp mysql-js.so /usr/lib/mysql/plugin/
10+
mysql test_udf -e 'CREATE FUNCTION execute_js RETURNS STRING SONAME "mysql-js.so"'
911

1012
test:
1113
mysql test_udf < test.sql
12-
mysql test_udf < test2.sql
1314

1415
restart:
1516
/etc/init.d/mysql restart
1617

1718
uninstall:
18-
rm /usr/lib/mysql/plugin/udf_example.so || true
1919
mysql test_udf -e 'DROP FUNCTION IF EXISTS execute_js;' || true
20+
rm /usr/lib/mysql/plugin/mysql-js.so || true
2021

2122
#gdb --args ./mysqld --defaults-file=my.ini --verbose --console -u root

js_require.hpp

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
const char* ToCString(const v8::String::Utf8Value& value) {
2+
return *value ? *value : "<string conversion failed>";
3+
}
4+
void ReportException(v8::TryCatch* try_catch) {
5+
v8::HandleScope handle_scope;
6+
v8::String::Utf8Value exception(try_catch->Exception());
7+
const char* exception_string = ToCString(exception);
8+
v8::Handle<v8::Message> message = try_catch->Message();
9+
if (message.IsEmpty()) {
10+
// V8 didn't provide any extra information about this error; just
11+
// print the exception.
12+
printf("%s\n", exception_string);
13+
} else {
14+
// Print (filename):(line number): (message).
15+
v8::String::Utf8Value filename(message->GetScriptResourceName());
16+
const char* filename_string = ToCString(filename);
17+
int linenum = message->GetLineNumber();
18+
printf("%s:%i: %s\n", filename_string, linenum, exception_string);
19+
// Print line of source code.
20+
v8::String::Utf8Value sourceline(message->GetSourceLine());
21+
const char* sourceline_string = ToCString(sourceline);
22+
printf("%s\n", sourceline_string);
23+
// Print wavy underline (GetUnderline is deprecated).
24+
int start = message->GetStartColumn();
25+
for (int i = 0; i < start; i++) {
26+
printf(" ");
27+
}
28+
int end = message->GetEndColumn();
29+
for (int i = start; i < end; i++) {
30+
printf("^");
31+
}
32+
printf("\n");
33+
v8::String::Utf8Value stack_trace(try_catch->StackTrace());
34+
if (stack_trace.length() > 0) {
35+
const char* stack_trace_string = ToCString(stack_trace);
36+
printf("%s\n", stack_trace_string);
37+
}
38+
}
39+
}
40+
// Reads a file into a v8 string.
41+
v8::Handle<v8::String> ReadFile(const char* name) {
42+
FILE* file = fopen(name, "rb");
43+
if (file == NULL) return v8::Handle<v8::String>();
44+
45+
fseek(file, 0, SEEK_END);
46+
int size = ftell(file);
47+
rewind(file);
48+
49+
char* chars = new char[size + 1];
50+
chars[size] = '\0';
51+
for (int i = 0; i < size;) {
52+
int read = fread(&chars[i], 1, size - i, file);
53+
i += read;
54+
}
55+
fclose(file);
56+
v8::Handle<v8::String> result = v8::String::New(chars, size);
57+
delete[] chars;
58+
return result;
59+
}
60+
// Executes a string within the current v8 context.
61+
bool ExecuteString(v8::Handle<v8::String> source,
62+
v8::Handle<v8::Value> name,
63+
bool print_result,
64+
bool report_exceptions) {
65+
v8::HandleScope handle_scope;
66+
v8::TryCatch try_catch;
67+
v8::Handle<v8::Script> script = v8::Script::Compile(source, name);
68+
if (script.IsEmpty()) {
69+
// Print errors that happened during compilation.
70+
if (report_exceptions)
71+
ReportException(&try_catch);
72+
return false;
73+
} else {
74+
v8::Handle<v8::Value> result = script->Run();
75+
if (result.IsEmpty()) {
76+
assert(try_catch.HasCaught());
77+
// Print errors that happened during execution.
78+
if (report_exceptions)
79+
ReportException(&try_catch);
80+
return false;
81+
} else {
82+
assert(!try_catch.HasCaught());
83+
if (print_result && !result->IsUndefined()) {
84+
// If all went well and the result wasn't undefined then print
85+
// the returned value.
86+
v8::String::Utf8Value str(result);
87+
const char* cstr = ToCString(str);
88+
printf("%s\n", cstr);
89+
}
90+
return true;
91+
}
92+
}
93+
}
94+
95+
v8::Handle<v8::Value> jsRequire(const v8::Arguments& args) {
96+
for (int i = 0; i < args.Length(); i++) {
97+
v8::HandleScope handle_scope;
98+
v8::String::Utf8Value file(args[i]);
99+
if (*file == NULL) {
100+
return v8::ThrowException(v8::String::New("Error loading file"));
101+
}
102+
v8::Handle<v8::String> source = ReadFile(*file);
103+
if (source.IsEmpty()) {
104+
return v8::ThrowException(v8::String::New("Error loading file"));
105+
}
106+
if (!ExecuteString(source, v8::String::New(*file), false, false)) {
107+
return v8::ThrowException(v8::String::New("Error executing file"));
108+
}
109+
}
110+
return v8::Undefined();
111+
}
112+

udf_example.cpp renamed to mysql-js.cpp

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,14 @@
1-
/* Copyright (C) 2002 MySQL AB
2-
3-
This program is free software; you can redistribute it and/or modify
4-
it under the terms of the GNU General Public License as published by
5-
the Free Software Foundation; version 2 of the License.
6-
7-
This program is distributed in the hope that it will be useful,
8-
but WITHOUT ANY WARRANTY; without even the implied warranty of
9-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10-
GNU General Public License for more details.
11-
12-
You should have received a copy of the GNU General Public License
13-
along with this program; if not, write to the Free Software
14-
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
15-
16-
1+
#define MYSQL_SERVER 1
172
#include <iostream>
183
#include <vector>
194
#include <my_global.h>
205
#include <my_sys.h>
21-
#include <m_string.h> //* To get strmov() *
6+
#include <m_string.h>
227
#include <string.h>
238
#include <mysql.h>
249
#include <ctype.h>
2510

26-
//#define MYSQL_SERVER 1
27-
//#include <mysql_priv.h>
11+
#include <mysql_priv.h>
2812

2913
extern "C" {
3014
my_bool execute_js_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
@@ -84,6 +68,9 @@ struct JsContext {
8468
Persistent<Object> gobject;
8569
};
8670

71+
#include "js_require.hpp"
72+
//#include "js_mysql.hpp"
73+
8774
my_bool execute_js_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
8875
{
8976
if (args->arg_count < 1 || args->arg_type[0] != STRING_RESULT) {
@@ -108,16 +95,23 @@ my_bool execute_js_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
10895
HandleScope handle_scope;
10996
//V8::GetCurrentThreadId();
11097

111-
ctx->context = Context::New();
98+
Handle<ObjectTemplate> global = ObjectTemplate::New();
99+
global->Set(v8::String::New("require"), ( v8::FunctionTemplate::New(jsRequire) ) );
100+
//global->Set(v8::String::New("find"), ( v8::FunctionTemplate::New(jsFind) ) );
101+
//Handle<Object> opts_obj = WrapMap(opts);
102+
103+
ctx->context = Context::New(NULL,global);
112104

113105
Context::Scope context_scope(ctx->context);
114106

115-
Handle<String> source = String::New(args->args[0],args->lengths[0]);
107+
Handle<v8::String> source = v8::String::New(args->args[0],args->lengths[0]);
116108
ctx->script = Persistent<Script>::New( Script::New(source) );
109+
ctx->gobject = Persistent<Object>::New( ctx->context->Global() );
110+
//jsMysqlCreateObjects(ctx->context->Global());
111+
117112
if (args->arg_count>1) {
118-
ctx->gobject = Persistent<Object>::New( ctx->context->Global() );
119113
ctx->script->Run();
120-
ctx->function = Persistent<Function>::New( Handle<Function>::Cast(ctx->gobject->Get(String::New(args->args[1],args->lengths[1]))) );
114+
ctx->function = Persistent<Function>::New( Handle<Function>::Cast(ctx->gobject->Get(v8::String::New(args->args[1],args->lengths[1]))) );
121115
}
122116
}
123117
return 0;
@@ -172,7 +166,7 @@ char *execute_js(UDF_INIT *initid __attribute__((unused)),
172166
if (args->arg_count>1) {
173167
Handle<Value> fargs[args->arg_count-2];
174168
for (int i=2;i<args->arg_count;i++) {
175-
fargs[i-2] = String::New(args->args[i],args->lengths[i]);
169+
fargs[i-2] = v8::String::New(args->args[i],args->lengths[i]);
176170
}
177171
jsresult = ctx->function->Call(ctx->function,args->arg_count-2, fargs);
178172
} else {
@@ -181,7 +175,7 @@ char *execute_js(UDF_INIT *initid __attribute__((unused)),
181175

182176
//jsresult = String::New("A");
183177

184-
String::Utf8Value res(jsresult);
178+
v8::String::Utf8Value res(jsresult);
185179
strncpy(result,*res,res.length());
186180
*length = res.length();
187181

File renamed without changes.

test.sql

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
DROP FUNCTION IF EXISTS execute_js;
2-
3-
CREATE FUNCTION execute_js RETURNS STRING SONAME "udf_example.so";
4-
51
SELECT execute_js("10+30");
2+
SELECT execute_js("10+30");
3+
SELECT execute_js("function asd(a,b) { return a+' '+b;};","asd","20","qwe");
4+
select execute_js("function asd(a,b) { var t = b+' '+a; return t.substring(12); };","asd","20",txt) as val from test.data limit 10;
5+
#select execute_js("find('test','data',2793)");
6+
#select execute_js("find('test','data',27931)");
7+
#select execute_js("for (var i=0;i<100000;i++) find('test','data',i)");

test2.sql

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)