Subversion Repositories HomeAutomation

Rev

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