Index: gears/database2/statement.cc =================================================================== --- gears/database2/statement.cc (revision 1609) +++ gears/database2/statement.cc (working copy) @@ -48,15 +48,135 @@ JsRootedCallback *callback, JsRootedCallback *error_callback, Database2Statement **instance) { - Database2Statement *statement = new Database2Statement(); + scoped_ptr statement; + statement.reset(new Database2Statement()); statement->sql_statement_.assign(sql_statement); statement->callback_.reset(callback); statement->error_callback_.reset(error_callback); - // TODO(dimitri.glazkov): convert sql_arguments to JsParamToSend[]. Accepted - // types are: double, int32, int64, string. All other types, are considered - // invalid - *instance = statement; - // TODO(dimitri.glazkov): decide whether ever return false (so that creator - // could throw an exception, for instance) or mark statement as bogus + + Database2Values *arguments; + if (!Database2Values::CreateFromJsArray(sql_arguments, &arguments)) { + return false; + } + + statement->arguments_.reset(arguments); + + *instance = statement.release(); return true; } + +// static +bool Database2Values::CreateFromJsArray(const JsArray &sql_arguments, + Database2Values **instance) { + scoped_ptr result; + result.reset(new Database2Values()); + + // since the arguments are optional, their token may be NULL + if (sql_arguments.token() == NULL) { + result->arguments_.reset(NULL); + result->length_ = 0; + *instance = result.release(); + return true; + } + + int len; + if (!sql_arguments.GetLength(&len)) { + // unable to query JsArray, someting's gone horribly wrong + // returning with failure will trigger an internal error + return false; + } + + result->length_ = len; + + result->arguments_.reset(new JsParamToSend[len]); + for(int i = 0; i < len; i++) { + if (!SetJsParamToSend(sql_arguments, i, result->arguments_.get())) { + // one invalid argument make the whole statement bogus + // no need to process any more parameters + // set length to only include last processed parameter + result->length_ = i; + return false; + } + } + + *instance = result.release(); + return true; +} + +// static +bool Database2Values::SetJsParamToSend(JsArray js_array, + int index, + JsParamToSend *arguments) { + assert(index >= 0 && arguments); + JsParamToSend *param = arguments + index; + param->type = js_array.GetElementType(index); + switch(param->type) { + case JSPARAM_INT: { + scoped_ptr value; + value.reset(new int); + if (js_array.GetElementAsInt(index, value.get())) { + param->value_ptr = value.release(); + return true; + } + return false; + } + case JSPARAM_DOUBLE: { + scoped_ptr value; + value.reset(new double); + if (js_array.GetElementAsDouble(index, value.get())) { + param->value_ptr = value.release(); + return true; + } + return false; + } + case JSPARAM_STRING16: { + scoped_ptr value; + value.reset(new std::string16()); + if (js_array.GetElementAsString(index, value.get())) { + param->value_ptr = value.release(); + return true; + } + return false; + } + case JSPARAM_NULL: { + param->value_ptr = NULL; + return true; + } + } + // all other types are considered invalid + return false; +} + +JsParamType Database2Values::GetType(int index) const { + assert(index >= 0 && index < length_); + return arguments_[index].type; +} + +int Database2Values::GetAsInt(int index) const { + assert(index >= 0 && index < length_); + JsParamToSend param = arguments_[index]; + assert(param.type == JSPARAM_INT); + return *static_cast(const_cast(param.value_ptr)); +} + +double Database2Values::GetAsDouble(int index) const { + assert(index >= 0 && index < length_); + JsParamToSend param = arguments_[index]; + assert(param.type == JSPARAM_DOUBLE); + return *static_cast(const_cast(param.value_ptr)); +} + +std::string16 &Database2Values::GetAsString(int index) const { + assert(index >= 0 && index < length_); + JsParamToSend param = arguments_[index]; + assert(param.type == JSPARAM_STRING16); + return *static_cast(const_cast(param.value_ptr)); +} + +Database2Values::~Database2Values() { + // dispose of the data, pointed to the value_ptrs + for(int i = 0; i < length_; i++) { + JsParamToSend param = arguments_[i]; + if (param.value_ptr) delete param.value_ptr; + } +}