Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(97)

Side by Side Diff: gears/database2/transaction.cc

Issue 717: Database2Values, argument conversion implemented (Closed) SVN Base: http://google-gears.googlecode.com/svn/contrib/dimitri.glazkov/database2/
Patch Set: ready for another look. Created 3 months, 2 weeks ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2008, Google Inc. 1 // Copyright 2008, Google Inc.
2 // 2 //
3 // Redistribution and use in source and binary forms, with or without 3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met: 4 // modification, are permitted provided that the following conditions are met:
5 // 5 //
6 // 1. Redistributions of source code must retain the above copyright notice, 6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer. 7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice, 8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation 9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution. 10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be 11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without 12 // used to endorse or promote products derived from this software without
13 // specific prior written permission. 13 // specific prior written permission.
14 // 14 //
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 25
26 #include "gears/database2/transaction.h" 26 #include "gears/database2/transaction.h"
27 27
28 #include "gears/base/common/dispatcher.h" 28 #include "gears/base/common/dispatcher.h"
29 #include "gears/base/common/js_types.h" 29 #include "gears/base/common/js_types.h"
30 #include "gears/base/common/js_runner.h" 30 #include "gears/base/common/js_runner.h"
31 #include "gears/base/common/module_wrapper.h" 31 #include "gears/base/common/module_wrapper.h"
32 #include "gears/database2/commands.h" 32 #include "gears/database2/commands.h"
33 #include "gears/database2/common.h" 33 #include "gears/database2/common.h"
34 #include "gears/database2/database2.h" 34 #include "gears/database2/database2.h"
35 #include "gears/database2/statement.h" 35 #include "gears/database2/statement.h"
36 36
37 DECLARE_GEARS_WRAPPER(Database2Transaction); 37 DECLARE_GEARS_WRAPPER(Database2Transaction);
38 38
39 template<> 39 template<>
40 void Dispatcher<Database2Transaction>::Init() { 40 void Dispatcher<Database2Transaction>::Init() {
41 RegisterMethod("executeSql", &Database2Transaction::ExecuteSql); 41 RegisterMethod("executeSql", &Database2Transaction::ExecuteSql);
42 } 42 }
43 43
44 44
45 // static 45 // static
46 bool Database2Transaction::Create( 46 bool Database2Transaction::Create(
47 const Database2 *database, 47 const Database2 *database,
48 Database2Connection *connection, 48 Database2Connection *connection,
49 Database2Interpreter *interpreter, 49 Database2Interpreter *interpreter,
50 JsRootedCallback *callback, 50 JsRootedCallback *callback,
51 JsRootedCallback *error_callback, 51 JsRootedCallback *error_callback,
52 JsRootedCallback *success_callback, 52 JsRootedCallback *success_callback,
53 scoped_refptr<Database2Transaction> *instance) { 53 scoped_refptr<Database2Transaction> *instance) {
54 assert(instance); 54 assert(instance);
55 if (!CreateModule<Database2Transaction>(database->GetJsRunner(), instance) 55 if (!CreateModule<Database2Transaction>(database->GetJsRunner(), instance)
56 || !instance->get()->InitBaseFromSibling(database)) { 56 || !instance->get()->InitBaseFromSibling(database)) {
57 return false; 57 return false;
58 } 58 }
59 59
60 Database2Transaction *tx = instance->get(); 60 Database2Transaction *tx = instance->get();
61 tx->connection_.reset(connection); 61 tx->connection_.reset(connection);
62 tx->interpreter_.reset(interpreter); 62 tx->interpreter_.reset(interpreter);
63 // set callbacks 63 // set callbacks
64 tx->callback_.reset(callback); 64 tx->callback_.reset(callback);
65 tx->error_callback_.reset(error_callback); 65 tx->error_callback_.reset(error_callback);
66 tx->success_callback_.reset(success_callback); 66 tx->success_callback_.reset(success_callback);
67 // register unload handler 67 // register unload handler
68 tx->unload_monitor_.reset(new JsEventMonitor(database->GetJsRunner(), 68 tx->unload_monitor_.reset(new JsEventMonitor(database->GetJsRunner(),
69 JSEVENT_UNLOAD, tx)); 69 JSEVENT_UNLOAD, tx));
70 return true; 70 return true;
71 } 71 }
72 72
73 void Database2Transaction::Start() { 73 void Database2Transaction::Start() {
74 // queue operation to begin transaction 74 // queue operation to begin transaction
75 interpreter_->Run(new Database2BeginCommand(this)); 75 interpreter_->Run(new Database2BeginCommand(this));
76 } 76 }
77 77
78 void Database2Transaction::InvokeCallback() { 78 void Database2Transaction::InvokeCallback() {
79 assert(callback_.get()); 79 assert(callback_.get());
80 // prepare to return transaction 80 // prepare to return transaction
81 JsParamToSend send_argv[] = { 81 JsParamToSend send_argv[] = {
82 { JSPARAM_DISPATCHER_MODULE, static_cast<ModuleImplBaseClass *>(this) } 82 { JSPARAM_DISPATCHER_MODULE, static_cast<ModuleImplBaseClass *>(this) }
83 }; 83 };
84 84
85 GetJsRunner()->InvokeCallback(callback_.get(), ARRAYSIZE(send_argv), 85 GetJsRunner()->InvokeCallback(callback_.get(), ARRAYSIZE(send_argv),
86 send_argv, NULL); 86 send_argv, NULL);
87 } 87 }
88 88
89 void Database2Transaction::ExecuteSql(JsCallContext *context) { 89 void Database2Transaction::ExecuteSql(JsCallContext *context) {
90 std::string16 sql_statement; 90 std::string16 sql_statement;
91 JsArray sql_arguments; 91 scoped_ptr<JsArray> sql_arguments(new JsArray());
92 JsRootedCallback *callback = NULL; 92 scoped_ptr<JsRootedCallback> callback;
93 JsRootedCallback *error_callback = NULL; 93 scoped_ptr<JsRootedCallback> error_callback;
94 JsArgument argv[] = { 94 JsArgument argv[] = {
95 { JSPARAM_REQUIRED, JSPARAM_STRING16, &sql_statement }, 95 { JSPARAM_REQUIRED, JSPARAM_STRING16, &sql_statement },
96 { JSPARAM_OPTIONAL, JSPARAM_ARRAY, &sql_arguments}, 96 { JSPARAM_OPTIONAL, JSPARAM_ARRAY, sql_arguments.get() },
97 { JSPARAM_OPTIONAL, JSPARAM_FUNCTION, &callback }, 97 { JSPARAM_OPTIONAL, JSPARAM_FUNCTION, callback.get() },
98 { JSPARAM_OPTIONAL, JSPARAM_FUNCTION, &error_callback } 98 { JSPARAM_OPTIONAL, JSPARAM_FUNCTION, error_callback.get() }
99 }; 99 };
100 100
101 context->GetArguments(ARRAYSIZE(argv), argv); 101 int argc = context->GetArguments(ARRAYSIZE(argv), argv);
102 if (context->is_exception_set()) return; 102 if (context->is_exception_set()) return;
103 103
104 if (!is_open_) { 104 if (!is_open_) {
105 context->SetException(kTransactionClosed); 105 context->SetException(kTransactionClosed);
106 return; 106 return;
107 } 107 }
108 108
109 // if any of the arguments are not supplied or null, send them to statement
110 // factory as NULL
111 if (argc < 2 || JsTokenIsNullOrUndefined(sql_arguments->token())) {
112 sql_arguments.reset(NULL);
113 }
114 if (argc < 3 || JsTokenIsNullOrUndefined(callback->token())) {
115 callback.reset(NULL);
116 }
117 if (argc < 4 || JsTokenIsNullOrUndefined(error_callback->token())) {
118 error_callback.reset(NULL);
119 }
120
109 Database2Statement *statement; 121 Database2Statement *statement;
110 if (!Database2Statement::Create(sql_statement, sql_arguments, callback, 122 if (!Database2Statement::Create(sql_statement, sql_arguments.get(),
111 error_callback, &statement)) { 123 callback.release(), error_callback.release(), &statement)) {
112 context->SetException(GET_INTERNAL_ERROR_MESSAGE()); 124 context->SetException(GET_INTERNAL_ERROR_MESSAGE());
113 return; 125 return;
114 } 126 }
115 127
116 bool first; 128 bool first;
117 // TODO(dimitri.glazkov): ideally, if the queue is empty prior to this 129 // TODO(dimitri.glazkov): ideally, if the queue is empty prior to this
118 // call, we should avoid pushing/popping the statement 130 // call, we should avoid pushing/popping the statement
119 statement_queue_.Push(statement, &first); 131 statement_queue_.Push(statement, &first);
120 if (first) { 132 if (first) {
121 ExecuteNextStatement(context); 133 ExecuteNextStatement(context);
122 } 134 }
123 // otherwise, the statement will be executed after the previous statement 135 // otherwise, the statement will be executed after the previous statement
124 // in queue 136 // in queue
125 } 137 }
126 138
127 void Database2Transaction::ExecuteNextStatement(JsCallContext *context) { 139 void Database2Transaction::ExecuteNextStatement(JsCallContext *context) {
128 // pop statement from the end of the queue 140 // pop statement from the end of the queue
129 bool empty; 141 bool empty;
130 Database2Statement *statement = statement_queue_.Pop(&empty); 142 Database2Statement *statement = statement_queue_.Pop(&empty);
131 // if no more statements, 143 // if no more statements,
132 if (empty) { 144 if (empty) {
133 interpreter_->Run(new Database2CommitCommand(this)); 145 interpreter_->Run(new Database2CommitCommand(this));
134 return; 146 return;
135 } 147 }
136 148
137 if (interpreter_->async()) { 149 if (interpreter_->async()) {
138 // interpreter_->Run(new Database2AsyncExecuteCommand(this)); 150 // interpreter_->Run(new Database2AsyncExecuteCommand(this));
139 } else { 151 } else {
140 assert(context); 152 assert(context);
141 interpreter_->Run(new Database2SyncExecuteCommand(this, context, 153 interpreter_->Run(new Database2SyncExecuteCommand(this, context,
142 statement)); 154 statement));
143 } 155 }
144 } 156 }
145 157
146 void Database2Transaction::InvokeErrorCallback() { 158 void Database2Transaction::InvokeErrorCallback() {
147 // for synchronous transaction, throw an error in case of transaction failure, 159 // for synchronous transaction, throw an error in case of transaction failure,
148 // otherwise, invoke callback or fail silently (per HTML5 spec) 160 // otherwise, invoke callback or fail silently (per HTML5 spec)
149 if (!interpreter_->async()) { 161 if (!interpreter_->async()) {
150 GetJsRunner()->ThrowGlobalError(connection()->error_message()); 162 GetJsRunner()->ThrowGlobalError(connection()->error_message());
151 return; 163 return;
152 } 164 }
153 165
154 if (!HasErrorCallback()) { 166 if (!HasErrorCallback()) {
155 return; 167 return;
156 } 168 }
157 169
158 JsObject* error = new JsObject(); 170 JsObject* error = new JsObject();
159 if (!Database2::CreateError(this, connection()->error_code(), 171 if (!Database2::CreateError(this, connection()->error_code(),
160 connection()->error_message(), error)) { 172 connection()->error_message(), error)) {
161 // unable to create an error object 173 // unable to create an error object
162 GetJsRunner()->ThrowGlobalError(GET_INTERNAL_ERROR_MESSAGE()); 174 GetJsRunner()->ThrowGlobalError(GET_INTERNAL_ERROR_MESSAGE());
163 return; 175 return;
164 } 176 }
165 177
166 JsParamToSend send_argv[] = { 178 JsParamToSend send_argv[] = {
167 JSPARAM_OBJECT, error 179 JSPARAM_OBJECT, error
168 }; 180 };
169 181
170 GetJsRunner()->InvokeCallback(error_callback_.get(), ARRAYSIZE(send_argv), 182 GetJsRunner()->InvokeCallback(error_callback_.get(), ARRAYSIZE(send_argv),
171 send_argv, NULL); 183 send_argv, NULL);
172 } 184 }
173 185
174 void Database2Transaction::InvokeSuccessCallback() { 186 void Database2Transaction::InvokeSuccessCallback() {
175 // success callback may only exist for asynchronous transaction 187 // success callback may only exist for asynchronous transaction
176 // InvokeSucessCallback() is called from CommitCommand, which doesn't know 188 // InvokeSucessCallback() is called from CommitCommand, which doesn't know
177 // whether it exists or not 189 // whether it exists or not
178 // TODO(dimitri.glazkov): think of a better pattern that doesn't cause 190 // TODO(dimitri.glazkov): think of a better pattern that doesn't cause
179 // conflating the execution path 191 // conflating the execution path
180 if (interpreter_->async() && HasSuccessCallback()) { 192 if (interpreter_->async() && HasSuccessCallback()) {
181 // TODO(dimitri.glazkov): investigate whether this is the right way to 193 // TODO(dimitri.glazkov): investigate whether this is the right way to
182 // invoke callback with no parameters 194 // invoke callback with no parameters
183 GetJsRunner()->InvokeCallback(success_callback_.get(), 0, NULL, NULL); 195 GetJsRunner()->InvokeCallback(success_callback_.get(), 0, NULL, NULL);
184 } 196 }
185 } 197 }
186 198
187 void Database2Transaction::HandleEvent(JsEventType event_type) { 199 void Database2Transaction::HandleEvent(JsEventType event_type) {
188 assert(event_type == JSEVENT_UNLOAD); 200 assert(event_type == JSEVENT_UNLOAD);
189 201
190 // clear callbacks, because in FF, the JS runtime may go away without 202 // clear callbacks, because in FF, the JS runtime may go away without
191 // finishing garbage-collection 203 // finishing garbage-collection
192 callback_.reset(); 204 callback_.reset();
193 error_callback_.reset(); 205 error_callback_.reset();
194 success_callback_.reset(); 206 success_callback_.reset();
195 207
196 unload_monitor_.reset(); 208 unload_monitor_.reset();
197 } 209 }
OLDNEW

Powered by Google App Engine
This is Rietveld r292