Subversion Repositories HomeAutomation

Rev

Rev 1945 | 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.   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.     ArgumentListPointer result_array = ArgumentListPointer(new ArgumentList);
  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.       throw atom::exception::action_failed();
  193.     }
  194.    
  195.    
  196.     /* Get the result */
  197.     result = mysql_store_result(MySql::resources_[(ResourceId)args[0]->Uint32Value()]);
  198.    
  199.     if (NULL == result)
  200.     {
  201.       if (mysql_field_count(MySql::resources_[(ResourceId)args[0]->Uint32Value()]) > 0)
  202.       {
  203.         throw atom::exception::action_failed();
  204.       }
  205.     }
  206.     else
  207.     {
  208.      
  209.       MYSQL_ROW           row;
  210.       uint32_t            number_of_fields = mysql_num_fields(result);
  211.       MYSQL_FIELD*        fields = mysql_fetch_fields(result);
  212.       uint32_t            row_index = 0;
  213.      
  214.       v8::Local<v8::Array> result_array = v8::Array::New();
  215.      
  216.      
  217.       while (NULL != (row = mysql_fetch_row(result)))
  218.       {
  219.         v8::Local<v8::Object> vars = v8::Object::New();
  220.    
  221.        
  222.         for (uint32_t index = 0; index < number_of_fields; index++)
  223.         {
  224.           vars->Set(v8::String::New(fields[index].name), v8::String::New(row[index]));
  225.          
  226. //          atom::log::Info(log_module_, "%s = %s\n", fields[index].name, row[index]);
  227.         }
  228.        
  229.         result_array->Set(row_index, vars);
  230.         row_index++;
  231.       }
  232.      
  233.       mysql_free_result(result);
  234.       result = NULL;
  235.      
  236.       return handle_scope.Close(v8::Handle<v8::Value>(result_array));
  237.     }
  238.    
  239.     return handle_scope.Close(v8::Boolean::New(true));
  240.   }
  241.   catch (std::exception& exception)
  242.   {
  243.     if (NULL != result)
  244.     {
  245.       mysql_free_result(result);
  246.       result = NULL;
  247.     }
  248.    
  249.     atom::log::Exception(log_module_, exception);
  250.    
  251.     return handle_scope.Close(v8::Boolean::New(false));
  252.   }
  253. }
  254.  
  255. Value MySql::Export_SelectDb(const v8::Arguments& args)
  256. {
  257.   ATOM_VM_PLUGIN_SCOPE;
  258.  
  259.   //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
  260.  
  261.   try
  262.   {
  263.     ATOM_VM_PLUGIN_NUM_PARAMS(2);
  264.  
  265.     v8::String::AsciiValue database(args[1]);
  266.    
  267.    
  268.     /* Check that the resource exist */
  269.     if (NULL == MySql::resources_[(ResourceId)args[0]->Uint32Value()])
  270.     {
  271.       throw atom::exception::missing_resource();
  272.     }
  273.    
  274.    
  275.     /* Select database */
  276.     if (0 != mysql_select_db(MySql::resources_[(ResourceId)args[0]->Uint32Value()], *database))
  277.     {
  278.        throw atom::exception::action_failed();
  279.     }
  280.    
  281.    
  282.     return handle_scope.Close(v8::Boolean::New(true));
  283.   }
  284.   catch (std::exception& exception)
  285.   {
  286.     atom::log::Exception(log_module_, exception);
  287.    
  288.     return handle_scope.Close(v8::Boolean::New(false));
  289.   }
  290. }
  291.  
  292. Value MySql::Export_AffectedRows(const v8::Arguments& args)
  293. {
  294.   ATOM_VM_PLUGIN_SCOPE;
  295.  
  296.   //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
  297.  
  298.   try
  299.   {
  300.     ATOM_VM_PLUGIN_NUM_PARAMS(1);
  301.  
  302.    
  303.     /* Check that the resource exist */
  304.     if (NULL == MySql::resources_[(ResourceId)args[0]->Uint32Value()])
  305.     {
  306.       throw atom::exception::missing_resource();
  307.     }
  308.    
  309.    
  310.     /* Select database */
  311.     uint32_t number_of_rows = mysql_affected_rows(MySql::resources_[(ResourceId)args[0]->Uint32Value()]);
  312.    
  313.    
  314.     return handle_scope.Close(v8::Uint32::New(number_of_rows));
  315.   }
  316.   catch (std::exception& exception)
  317.   {
  318.     atom::log::Exception(log_module_, exception);
  319.    
  320.     return handle_scope.Close(v8::Boolean::New(false));
  321.   }
  322. }
  323.  
  324. Value MySql::Export_InsertId(const v8::Arguments& args)
  325. {
  326.   ATOM_VM_PLUGIN_SCOPE;
  327.  
  328.   //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
  329.  
  330.   try
  331.   {
  332.     ATOM_VM_PLUGIN_NUM_PARAMS(1);
  333.  
  334.    
  335.     /* Check that the resource exist */
  336.     if (NULL == MySql::resources_[(ResourceId)args[0]->Uint32Value()])
  337.     {
  338.       throw atom::exception::missing_resource();
  339.     }
  340.    
  341.    
  342.     /* Select database */
  343.     uint32_t insert_id = mysql_insert_id(MySql::resources_[(ResourceId)args[0]->Uint32Value()]);
  344.    
  345.    
  346.     return handle_scope.Close(v8::Uint32::New(insert_id));
  347.   }
  348.   catch (std::exception& exception)
  349.   {
  350.     atom::log::Exception(log_module_, exception);
  351.    
  352.     return handle_scope.Close(v8::Boolean::New(false));
  353.   }
  354. }
  355.  
  356. }; // namespace plugin
  357. }; // namespace vm
  358. }; // namespace atom
  359.