Subversion Repositories HomeAutomation

Rev

Rev 1950 | 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.   this->ExportFunction("MySqlExport_InsertId",      MySql::Export_InsertId);
  48. }
  49.  
  50. MySql::~MySql()
  51. {
  52. }
  53.  
  54. void MySql::InitializeDone()
  55. {
  56.   Plugin::InitializeDone();
  57. }
  58.  
  59. void MySql::CallOutput(unsigned int request_id, std::string output)
  60. {
  61.   atom::log::Info(log_module_, output);
  62. }
  63.  
  64. MySql::ResourceId MySql::GetFreeResourceId()
  65. {
  66.   ResourceId resource_id = 1;
  67.    
  68.   while (NULL != MySql::resources_[resource_id])
  69.   {
  70.     resource_id++;
  71.   }
  72.  
  73.   return resource_id;
  74. }
  75.  
  76. Value MySql::Export_Connect(const v8::Arguments& args)
  77. {
  78.   ATOM_VM_PLUGIN_SCOPE;
  79.  
  80.   MYSQL*      resource = NULL;
  81.   ResourceId  resource_id;
  82.  
  83.   //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
  84.  
  85.   try
  86.   {
  87.     ATOM_VM_PLUGIN_NUM_PARAMS(3);
  88.  
  89.     v8::String::AsciiValue server(args[0]);
  90.     v8::String::AsciiValue username(args[1]);
  91.     v8::String::AsciiValue password(args[2]);
  92.    
  93.    
  94.     /* Initialize MySQL resource */
  95.     resource = mysql_init(NULL);
  96.  
  97.     if (NULL == resource)
  98.     {
  99.       throw atom::exception::initialization_failed();
  100.     }
  101.    
  102.    
  103.     /* Connect to database */
  104.     if (mysql_real_connect(resource, *server, *username, *password, NULL, 0, NULL, 0) == NULL)
  105.     {
  106.       atom::log::Error(log_module_, "Failed to connect to database %s, error code %d, error message \"%s\".", *server, mysql_errno(resource), mysql_error(resource));
  107.       throw atom::exception::connect_failed();
  108.     }
  109.  
  110.    
  111.     /* Add resource to list */
  112.     resource_id = MySql::GetFreeResourceId();
  113.     MySql::resources_[resource_id] = resource;
  114.  
  115.    
  116.     return handle_scope.Close(v8::Uint32::New(resource_id));
  117.   }
  118.   catch (std::exception& exception)
  119.   {
  120.     if (NULL != resource)
  121.     {
  122.       mysql_close(resource);
  123.       resource = NULL;
  124.     }
  125.    
  126.     atom::log::Exception(log_module_, exception);
  127.    
  128.     return handle_scope.Close(v8::Boolean::New(false));
  129.   }
  130. }
  131.  
  132. Value MySql::Export_Close(const v8::Arguments& args)
  133. {
  134.   ATOM_VM_PLUGIN_SCOPE;
  135.  
  136.   //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
  137.  
  138.   try
  139.   {
  140.     ATOM_VM_PLUGIN_NUM_PARAMS(1);
  141.  
  142.    
  143.     /* Check that the resource exist */
  144.     if (NULL == MySql::resources_[(ResourceId)args[0]->Uint32Value()])
  145.     {
  146.       throw atom::exception::missing_resource();
  147.     }
  148.    
  149.    
  150.     /* Close connection */
  151.     mysql_close(MySql::resources_[(ResourceId)args[0]->Uint32Value()]);
  152.     MySql::resources_.erase((ResourceId)args[0]->Uint32Value());
  153.    
  154.    
  155.     return handle_scope.Close(v8::Boolean::New(true));
  156.   }
  157.   catch (std::exception& exception)
  158.   {
  159.     atom::log::Exception(log_module_, exception);
  160.    
  161.     return handle_scope.Close(v8::Boolean::New(false));
  162.   }
  163. }
  164.  
  165. Value MySql::Export_Query(const v8::Arguments& args)
  166. {
  167.   ATOM_VM_PLUGIN_SCOPE;
  168.  
  169.   MYSQL_RES* result = NULL;
  170.  
  171.   //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
  172.  
  173.   try
  174.   {
  175.     v8::Local<v8::Array> result_array = v8::Array::New();
  176.    
  177.     ATOM_VM_PLUGIN_NUM_PARAMS(2);
  178.  
  179.     v8::String::AsciiValue query(args[1]);
  180.    
  181.    
  182.     /* Check that the resource exist */
  183.     if (NULL == MySql::resources_[(ResourceId)args[0]->Uint32Value()])
  184.     {
  185.       throw atom::exception::missing_resource();
  186.     }
  187.    
  188.    
  189.     /* Execute the query */
  190.     if (0 != mysql_query(MySql::resources_[(ResourceId)args[0]->Uint32Value()], *query))
  191.     {
  192.       atom::log::Error(log_module_, "Failed to execute query \"%s\", error code %d, error message \"%s\".", *query, mysql_errno(MySql::resources_[(ResourceId)args[0]->Uint32Value()]), mysql_error(MySql::resources_[(ResourceId)args[0]->Uint32Value()]));
  193.       throw atom::exception::action_failed();
  194.     }
  195.    
  196.    
  197.     /* Get the result */
  198.     result = mysql_store_result(MySql::resources_[(ResourceId)args[0]->Uint32Value()]);
  199.    
  200.     if (NULL == result)
  201.     {
  202.       if (mysql_field_count(MySql::resources_[(ResourceId)args[0]->Uint32Value()]) > 0)
  203.       {
  204.         atom::log::Error(log_module_, "Supposed to get data but got none!");
  205.         throw atom::exception::action_failed();
  206.       }
  207.     }
  208.     else
  209.     {
  210.      
  211.       MYSQL_ROW     row;
  212.       uint32_t      number_of_fields = mysql_num_fields(result);
  213.       MYSQL_FIELD*  fields = mysql_fetch_fields(result);
  214.       uint32_t      row_index = 0;
  215.      
  216.       while (NULL != (row = mysql_fetch_row(result)))
  217.       {
  218.         v8::Local<v8::Object> vars = v8::Object::New();
  219.    
  220.        
  221.         for (uint32_t index = 0; index < number_of_fields; index++)
  222.         {
  223.           vars->Set(v8::String::New(fields[index].name), v8::String::New(row[index]));
  224.          
  225. //          atom::log::Info(log_module_, "%s = %s\n", fields[index].name, row[index]);
  226.         }
  227.        
  228.         result_array->Set(row_index, vars);
  229.         row_index++;
  230.       }
  231.      
  232.       mysql_free_result(result);
  233.       result = NULL;
  234.     }
  235.    
  236.     return handle_scope.Close(v8::Handle<v8::Value>(result_array));
  237.   }
  238.   catch (std::exception& exception)
  239.   {
  240.     if (NULL != result)
  241.     {
  242.       mysql_free_result(result);
  243.       result = NULL;
  244.     }
  245.    
  246.     atom::log::Exception(log_module_, exception);
  247.    
  248.     return handle_scope.Close(v8::Boolean::New(false));
  249.   }
  250. }
  251.  
  252. Value MySql::Export_SelectDb(const v8::Arguments& args)
  253. {
  254.   ATOM_VM_PLUGIN_SCOPE;
  255.  
  256.   //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
  257.  
  258.   try
  259.   {
  260.     ATOM_VM_PLUGIN_NUM_PARAMS(2);
  261.  
  262.     v8::String::AsciiValue database(args[1]);
  263.    
  264.    
  265.     /* Check that the resource exist */
  266.     if (NULL == MySql::resources_[(ResourceId)args[0]->Uint32Value()])
  267.     {
  268.       throw atom::exception::missing_resource();
  269.     }
  270.    
  271.    
  272.     /* Select database */
  273.     if (0 != mysql_select_db(MySql::resources_[(ResourceId)args[0]->Uint32Value()], *database))
  274.     {
  275.       atom::log::Error(log_module_, "Failed to select database \"%s\", error code %d, error message \"%s\".", *database, mysql_errno(MySql::resources_[(ResourceId)args[0]->Uint32Value()]), mysql_error(MySql::resources_[(ResourceId)args[0]->Uint32Value()]));
  276.       throw atom::exception::action_failed();
  277.     }
  278.    
  279.    
  280.     return handle_scope.Close(v8::Boolean::New(true));
  281.   }
  282.   catch (std::exception& exception)
  283.   {
  284.     atom::log::Exception(log_module_, exception);
  285.    
  286.     return handle_scope.Close(v8::Boolean::New(false));
  287.   }
  288. }
  289.  
  290. Value MySql::Export_AffectedRows(const v8::Arguments& args)
  291. {
  292.   ATOM_VM_PLUGIN_SCOPE;
  293.  
  294.   //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
  295.  
  296.   try
  297.   {
  298.     ATOM_VM_PLUGIN_NUM_PARAMS(1);
  299.  
  300.    
  301.     /* Check that the resource exist */
  302.     if (NULL == MySql::resources_[(ResourceId)args[0]->Uint32Value()])
  303.     {
  304.       throw atom::exception::missing_resource();
  305.     }
  306.    
  307.    
  308.     /* Select database */
  309.     uint32_t number_of_rows = mysql_affected_rows(MySql::resources_[(ResourceId)args[0]->Uint32Value()]);
  310.    
  311.    
  312.     return handle_scope.Close(v8::Uint32::New(number_of_rows));
  313.   }
  314.   catch (std::exception& exception)
  315.   {
  316.     atom::log::Exception(log_module_, exception);
  317.    
  318.     return handle_scope.Close(v8::Boolean::New(false));
  319.   }
  320. }
  321.  
  322. Value MySql::Export_InsertId(const v8::Arguments& args)
  323. {
  324.   ATOM_VM_PLUGIN_SCOPE;
  325.  
  326.   //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
  327.  
  328.   try
  329.   {
  330.     ATOM_VM_PLUGIN_NUM_PARAMS(1);
  331.  
  332.    
  333.     /* Check that the resource exist */
  334.     if (NULL == MySql::resources_[(ResourceId)args[0]->Uint32Value()])
  335.     {
  336.       throw atom::exception::missing_resource();
  337.     }
  338.    
  339.    
  340.     /* Select database */
  341.     uint32_t insert_id = mysql_insert_id(MySql::resources_[(ResourceId)args[0]->Uint32Value()]);
  342.    
  343.    
  344.     return handle_scope.Close(v8::Uint32::New(insert_id));
  345.   }
  346.   catch (std::exception& exception)
  347.   {
  348.     atom::log::Exception(log_module_, exception);
  349.    
  350.     return handle_scope.Close(v8::Boolean::New(false));
  351.   }
  352. }
  353.  
  354. }; // namespace plugin
  355. }; // namespace vm
  356. }; // namespace atom
  357.