-
Notifications
You must be signed in to change notification settings - Fork 97
Expand file tree
/
Copy pathstatement.cpp
More file actions
107 lines (82 loc) · 2.99 KB
/
statement.cpp
File metadata and controls
107 lines (82 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <string.h>
#include "connection.h"
#include "executeBaton.h"
#include "statement.h"
using namespace std;
Persistent<FunctionTemplate> Statement::constructorTemplate;
void Statement::Init(Handle<Object> target) {
UNI_SCOPE(scope);
Local<FunctionTemplate> t = NanNew<FunctionTemplate>(New);
uni::Reset(constructorTemplate, t);
uni::Deref(constructorTemplate)->InstanceTemplate()->SetInternalFieldCount(1);
uni::Deref(constructorTemplate)->SetClassName(NanNew<String>("Statement"));
NODE_SET_PROTOTYPE_METHOD(uni::Deref(constructorTemplate), "execute", Execute);
target->Set(NanNew<String>("Statement"), uni::Deref(constructorTemplate)->GetFunction());
}
Statement::Statement(): ObjectWrap() {
}
Statement::~Statement() {
delete m_baton;
m_baton = NULL;
}
uni::CallbackType Statement::New(const uni::FunctionCallbackInfo& args) {
UNI_SCOPE(scope);
Statement* statement = new Statement();
statement->Wrap(args.This());
UNI_RETURN(scope, args, args.This());
}
void Statement::setBaton(StatementBaton* baton) {
m_baton = baton;
}
uni::CallbackType Statement::Execute(const uni::FunctionCallbackInfo& args) {
UNI_SCOPE(scope);
Statement* statement = ObjectWrap::Unwrap<Statement>(args.This());
StatementBaton* baton = statement->m_baton;
REQ_ARRAY_ARG(0, values);
REQ_FUN_ARG(1, callback);
uni::Reset(baton->callback, callback);
ExecuteBaton::CopyValuesToBaton(baton, &values);
if (baton->error) {
Local<String> message = NanNew<String>(baton->error->c_str());
UNI_THROW(Exception::Error(message));
}
if (baton->busy) {
UNI_THROW(Exception::Error(NanNew<String>("invalid state: statement is busy with another execute call")));
}
baton->busy = true;
uv_work_t* req = new uv_work_t();
req->data = baton;
uv_queue_work(uv_default_loop(), req, EIO_Execute, (uv_after_work_cb)EIO_AfterExecute);
baton->connection->Ref();
UNI_RETURN(scope, args, NanUndefined());
}
void Statement::EIO_Execute(uv_work_t* req) {
StatementBaton* baton = static_cast<StatementBaton*>(req->data);
if (!baton->connection->getConnection()) {
baton->error = new std::string("Connection already closed");
return;
}
if (!baton->stmt) {
baton->stmt = Connection::CreateStatement(baton);
if (baton->error) return;
}
Connection::ExecuteStatement(baton, baton->stmt);
}
void Statement::EIO_AfterExecute(uv_work_t* req, int status) {
UNI_SCOPE(scope);
StatementBaton* baton = static_cast<StatementBaton*>(req->data);
baton->busy = false;
baton->connection->Unref();
// transfer callback to local and dispose persistent handle
Local<Function> cb = uni::HandleToLocal(uni::Deref(baton->callback));
NanDisposePersistent(baton->callback);
Handle<Value> argv[2];
Connection::handleResult(baton, argv);
baton->ResetValues();
baton->ResetRows();
baton->ResetOutputs();
baton->ResetError();
delete req;
// invoke callback at the very end because callback may re-enter execute.
NanMakeCallback(NanGetCurrentContext()->Global(), cb, 2, argv);
}