Subversion Repositories HomeAutomation

Rev

Rev 1950 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /*
  2.  *
  3.  *  Copyright (C) 2012  Mattias Runge
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License along
  16.  *  with this program; if not, write to the Free Software Foundation, Inc.,
  17.  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18.  *
  19.  */
  20.  
  21. #include "MySql.h"
  22.  
  23. #include <mysql.h>
  24. #include <boost/lexical_cast.hpp>
  25.  
  26. #include "vm/Manager.h"
  27. #include "common/log.h"
  28. #include "common/exception.h"
  29.  
  30. namespace atom {
  31. namespace vm {
  32. namespace plugin {
  33.  
  34. MySql::Resources MySql::resources_;
  35.  
  36. static const std::string log_module_ = "vm::plugin::mysql";
  37.  
  38. MySql::MySql(boost::asio::io_service& io_service) : Plugin(io_service)
  39. {
  40.   this->name_ = "mysql";
  41.  
  42.   this->ExportFunction("MySqlExport_Connect",       MySql::Export_Connect);
  43.   this->ExportFunction("MySqlExport_Close",         MySql::Export_Close);
  44.   this->ExportFunction("MySqlExport_Query",         MySql::Export_Query);
  45.   this->ExportFunction("MySqlExport_SelectDb",      MySql::Export_SelectDb);
  46.   this->ExportFunction("MySqlExport_AffectedRows",  MySql::Export_AffectedRows);
  47. }
  48.  
  49. MySql::~MySql()
  50. {
  51. }
  52.  
  53. void MySql::InitializeDone()
  54. {
  55.   Plugin::InitializeDone();
  56. }
  57.  
  58. void MySql::CallOutput(unsigned int request_id, std::string output)
  59. {
  60.   atom::log::Info(log_module_, output);
  61. }
  62.  
  63. Value MySql::Export_Connect(const v8::Arguments& args)
  64. {
  65.   ATOM_VM_PLUGIN_SCOPE;
  66.  
  67.   MYSQL* resource = NULL;
  68.  
  69.   atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
  70.  
  71.   try
  72.   {
  73.     ATOM_VM_PLUGIN_NUM_PARAMS(3);
  74.  
  75.     v8::String::AsciiValue server(args[0]);
  76.     v8::String::AsciiValue username(args[1]);
  77.     v8::String::AsciiValue password(args[2]);
  78.    
  79.    
  80.     /* Initialize MySQL resource */
  81.     resource = mysql_init(NULL);
  82.  
  83.     if (NULL == resource)
  84.     {
  85.       throw atom::exception::initialization_failed;
  86.     }
  87.    
  88.    
  89.     /* Connect to database */
  90.     if (mysql_real_connect(resource, *server, *username, *password, NULL, 0, NULL, 0) == NULL)
  91.     {
  92.       atom::log::Error(log_module_, "Failed to connect to database %s, error code %d, error message \"%s\".", *server, mysql_errno(resource), mysql_error(resource));
  93.       throw atom::exception::connect_failed;
  94.     }
  95.  
  96.    
  97.     /* Add resource to list */
  98.     MySql::resources_[(uintptr_t)resource] = resource;
  99.  
  100.    
  101.     return handle_scope.Close(v8::Uint32::New((uintptr_t)resource));
  102.   }
  103.   catch (std::exception& exception)
  104.   {
  105.     if (NULL != resource)
  106.     {
  107.       mysql_close(resource);
  108.       resource = NULL;
  109.     }
  110.    
  111.     atom::log::Exception(log_module_, exception);
  112.    
  113.     return handle_scope.Close(v8::Boolean::New(false));
  114.   }
  115. }
  116.  
  117. Value MySql::Export_Close(const v8::Arguments& args)
  118. {
  119.   ATOM_VM_PLUGIN_SCOPE;
  120.  
  121.   atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
  122.  
  123.   try
  124.   {
  125.     ATOM_VM_PLUGIN_NUM_PARAMS(1);
  126.  
  127.    
  128.     /* Check that the resource exist */
  129.     if (NULL == MySql::resources_[(uintptr_t)args[0]->Uint32Value()])
  130.     {
  131.       throw atom::exception::missing_resource;
  132.     }
  133.    
  134.    
  135.     /* Close connection */
  136.     mysql_close(MySql::resources_[(uintptr_t)args[0]->Uint32Value()]);
  137.     MySql::resources_.erase((uintptr_t)args[0]->Uint32Value());
  138.    
  139.    
  140.     return handle_scope.Close(v8::Boolean::New(true));
  141.   }
  142.   catch (std::exception& exception)
  143.   {
  144.     atom::log::Exception(log_module_, exception);
  145.    
  146.     return handle_scope.Close(v8::Boolean::New(false));
  147.   }
  148. }
  149.  
  150. Value MySql::Export_Query(const v8::Arguments& args)
  151. {
  152.   ATOM_VM_PLUGIN_SCOPE;
  153.  
  154.   MYSQL_RES* result = NULL;
  155.  
  156.   atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
  157.  
  158.   try
  159.   {
  160.     ArgumentListPointer result_array = ArgumentListPointer(new ArgumentList);
  161.    
  162.     ATOM_VM_PLUGIN_NUM_PARAMS(2);
  163.  
  164.     v8::String::AsciiValue query(args[1]);
  165.    
  166.    
  167.     /* Check that the resource exist */
  168.     if (NULL == MySql::resources_[(uintptr_t)args[0]->Uint32Value()])
  169.     {
  170.       throw atom::exception::missing_resource;
  171.     }
  172.    
  173.    
  174.     /* Execute the query */
  175.     if (0 != mysql_query(MySql::resources_[(uintptr_t)args[0]->Uint32Value()], *query))
  176.     {
  177.       throw atom::exception::action_failed;
  178.     }
  179.    
  180.    
  181.     /* Get the result */
  182.     result = mysql_store_result(MySql::resources_[(uintptr_t)args[0]->Uint32Value()]);
  183.    
  184.     if (NULL == result)
  185.     {
  186.       if (mysql_field_count(MySql::resources_[(uintptr_t)args[0]->Uint32Value()]) > 0)
  187.       {
  188.         throw atom::exception::action_failed;
  189.       }
  190.     }
  191.     else
  192.     {
  193.      
  194.       MYSQL_ROW           row;
  195.       uint32_t            number_of_fields = mysql_num_fields(result);
  196.       MYSQL_FIELD*        fields = mysql_fetch_fields(result);
  197.       uint32_t            row_index = 0;
  198.      
  199.       v8::Local<v8::Array> result_array = v8::Array::New();
  200.      
  201.      
  202.       while (NULL != (row = mysql_fetch_row(result)))
  203.       {
  204.         v8::Local<v8::Object> vars = v8::Object::New();
  205.    
  206.        
  207.         for (uint32_t index = 0; index < number_of_fields; index++)
  208.         {
  209.           vars->Set(v8::String::New(fields[index].name), v8::String::New(row[index]));
  210.          
  211. //          atom::log::Info(log_module_, "%s = %s\n", fields[index].name, row[index]);
  212.         }
  213.        
  214.         result_array->Set(row_index, vars);
  215.         row_index++;
  216.       }
  217.      
  218.       mysql_free_result(result);
  219.       result = NULL;
  220.      
  221.       return handle_scope.Close(v8::Handle<v8::Value>(result_array));
  222.     }
  223.    
  224.     return handle_scope.Close(v8::Boolean::New(true));
  225.   }
  226.   catch (std::exception& exception)
  227.   {
  228.     if (NULL != result)
  229.     {
  230.       mysql_free_result(result);
  231.       result = NULL;
  232.     }
  233.    
  234.     atom::log::Exception(log_module_, exception);
  235.    
  236.     return handle_scope.Close(v8::Boolean::New(false));
  237.   }
  238. }
  239.  
  240. Value MySql::Export_SelectDb(const v8::Arguments& args)
  241. {
  242.   ATOM_VM_PLUGIN_SCOPE;
  243.  
  244.   atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
  245.  
  246.   try
  247.   {
  248.     ATOM_VM_PLUGIN_NUM_PARAMS(2);
  249.  
  250.     v8::String::AsciiValue database(args[1]);
  251.    
  252.    
  253.     /* Check that the resource exist */
  254.     if (NULL == MySql::resources_[(uintptr_t)args[0]->Uint32Value()])
  255.     {
  256.       throw atom::exception::missing_resource;
  257.     }
  258.    
  259.    
  260.     /* Select database */
  261.     if (0 != mysql_select_db(MySql::resources_[(uintptr_t)args[0]->Uint32Value()], *database))
  262.     {
  263.        throw atom::exception::action_failed;
  264.     }
  265.    
  266.    
  267.     return handle_scope.Close(v8::Boolean::New(true));
  268.   }
  269.   catch (std::exception& exception)
  270.   {
  271.     atom::log::Exception(log_module_, exception);
  272.    
  273.     return handle_scope.Close(v8::Boolean::New(false));
  274.   }
  275. }
  276.  
  277. Value MySql::Export_AffectedRows(const v8::Arguments& args)
  278. {
  279.   ATOM_VM_PLUGIN_SCOPE;
  280.  
  281.   atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
  282.  
  283.   try
  284.   {
  285.     ATOM_VM_PLUGIN_NUM_PARAMS(1);
  286.  
  287.    
  288.     /* Check that the resource exist */
  289.     if (NULL == MySql::resources_[(uintptr_t)args[0]->Uint32Value()])
  290.     {
  291.       throw atom::exception::missing_resource;
  292.     }
  293.    
  294.    
  295.     /* Select database */
  296.     uint32_t number_of_rows = mysql_affected_rows(MySql::resources_[(uintptr_t)args[0]->Uint32Value()]);
  297.    
  298.    
  299.     return handle_scope.Close(v8::Uint32::New(number_of_rows));
  300.   }
  301.   catch (std::exception& exception)
  302.   {
  303.     atom::log::Exception(log_module_, exception);
  304.    
  305.     return handle_scope.Close(v8::Boolean::New(false));
  306.   }
  307. }
  308.  
  309.  
  310. }; // namespace plugin
  311. }; // namespace vm
  312. }; // namespace atom
  313.