ClosestStorm / v8cgi

Automatically exported from code.google.com/p/v8cgi
BSD 3-Clause "New" or "Revised" License
0 stars 1 forks source link

mysql prepared statement proof of concept #113

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
I really want prepared statement functionality for mysql so I wrote a little 
proof of concept.
It can be used like this: db.prepared("insert into log 
values(0,?,?)",[123,"abc"]);
I'm new to v8 and v8cgi and haven't used the mysql C api that much either but 
the code works so far.
It's not complete, I don't bother freeing memory, etc. - but if there is 
interest in including something like this I could improve and maintain it.

JS_METHOD(_prepared) {
   MYSQL_PTR;
   ASSERT_CONNECTED;
   if (args.Length() < 1) {
      return JS_ERROR("No query specified");
   }
   if (args.Length() < 2 || !args[1]->IsArray()) {
      return JS_ERROR("no prepare stuff");
   }
   if (args.Length() > 2) {
      return JS_ERROR("too many args");
   }
   v8::Handle<v8::Array> js_query_params = v8::Handle<v8::Array>::Cast(args[1]);
   if (js_query_params->Length()<=0) {
      return JS_ERROR("prepared param array empty");
   }

   MYSQL_STMT *stmt;
   {
      stmt = mysql_stmt_init(conn);
      v8::String::Utf8Value q(args[0]);
      if (mysql_stmt_prepare(stmt, *q, q.length()) != 0) {
         return JS_ERROR(MYSQL_ERROR);
      }
   }
   MYSQL_BIND c_query_params[js_query_params->Length()];

   for (unsigned int i = 0; i < js_query_params->Length(); i++) {
      if (js_query_params->Get(i)->IsString()) {
         v8::String::Utf8Value s(js_query_params->Get(i));
         c_query_params[i].buffer_type = MYSQL_TYPE_VAR_STRING;
         c_query_params[i].buffer = strndup(*s,s.length()+1);
         c_query_params[i].is_unsigned = 0;
         c_query_params[i].is_null = 0;
         c_query_params[i].length = new unsigned long(s.length());
         continue;
      }
      if (js_query_params->Get(i)->IsNumber()) {
         v8::Handle<v8::Number> n=v8::Handle<v8::Number>::Cast(js_query_params->Get(i));
         c_query_params[i].buffer_type = MYSQL_TYPE_DOUBLE;
         c_query_params[i].buffer = new double((*n)->Value());
         c_query_params[i].is_unsigned = 0;
         c_query_params[i].is_null = 0;
         c_query_params[i].length = 0;
         continue;
      }
      return JS_ERROR("invalid type for prepared arg");
   }

   if(mysql_stmt_bind_param(stmt, c_query_params) != 0) {
      return JS_ERROR(MYSQL_ERROR);
   }

   int code = mysql_stmt_execute(stmt);
   if (code != 0) { return JS_ERROR(MYSQL_ERROR); }
   int qc = args.This()->Get(JS_STR("queryCount"))->ToInteger()->Int32Value();
   args.This()->Set(JS_STR("queryCount"), JS_INT(qc+1));

   return createResult(conn);
}

Original issue reported on code.google.com by rom.p.k...@gmail.com on 7 May 2012 at 12:36

GoogleCodeExporter commented 9 years ago
Cool, thanks! This brings prepared statements closer to completion :-)

Original comment by ondrej.zara on 7 May 2012 at 6:04