Subversion Repositories HomeAutomation

Rev

Rev 1950 | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
1945 runge 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);
1947 runge 47
  this->ExportFunction("MySqlExport_InsertId",      MySql::Export_InsertId);
1945 runge 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
 
1947 runge 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
 
1945 runge 76
Value MySql::Export_Connect(const v8::Arguments& args)
77
{
78
  ATOM_VM_PLUGIN_SCOPE;
79
 
1947 runge 80
  MYSQL*      resource = NULL;
81
  ResourceId  resource_id;
1945 runge 82
 
1947 runge 83
  //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
1945 runge 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
    {
1947 runge 99
      throw atom::exception::initialization_failed();
1945 runge 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));
1947 runge 107
      throw atom::exception::connect_failed();
1945 runge 108
    }
109
 
110
 
111
    /* Add resource to list */
1947 runge 112
    resource_id = MySql::GetFreeResourceId();
113
    MySql::resources_[resource_id] = resource;
1945 runge 114
 
115
 
1947 runge 116
    return handle_scope.Close(v8::Uint32::New(resource_id));
1945 runge 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
 
1947 runge 136
  //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
1945 runge 137
 
138
  try
139
  {
140
    ATOM_VM_PLUGIN_NUM_PARAMS(1);
141
 
142
 
143
    /* Check that the resource exist */
1947 runge 144
    if (NULL == MySql::resources_[(ResourceId)args[0]->Uint32Value()])
1945 runge 145
    {
1947 runge 146
      throw atom::exception::missing_resource();
1945 runge 147
    }
148
 
149
 
150
    /* Close connection */
1947 runge 151
    mysql_close(MySql::resources_[(ResourceId)args[0]->Uint32Value()]);
152
    MySql::resources_.erase((ResourceId)args[0]->Uint32Value());
1945 runge 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
 
1947 runge 171
  //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
1945 runge 172
 
173
  try
174
  {
1952 runge 175
    v8::Local<v8::Array> result_array = v8::Array::New();
1945 runge 176
 
177
    ATOM_VM_PLUGIN_NUM_PARAMS(2);
178
 
179
    v8::String::AsciiValue query(args[1]);
180
 
181
 
182
    /* Check that the resource exist */
1947 runge 183
    if (NULL == MySql::resources_[(ResourceId)args[0]->Uint32Value()])
1945 runge 184
    {
1947 runge 185
      throw atom::exception::missing_resource();
1945 runge 186
    }
187
 
188
 
189
    /* Execute the query */
1947 runge 190
    if (0 != mysql_query(MySql::resources_[(ResourceId)args[0]->Uint32Value()], *query))
1945 runge 191
    {
1950 runge 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()]));
1947 runge 193
      throw atom::exception::action_failed();
1945 runge 194
    }
195
 
196
 
197
    /* Get the result */
1947 runge 198
    result = mysql_store_result(MySql::resources_[(ResourceId)args[0]->Uint32Value()]);
1945 runge 199
 
200
    if (NULL == result)
201
    {
1947 runge 202
      if (mysql_field_count(MySql::resources_[(ResourceId)args[0]->Uint32Value()]) > 0)
1945 runge 203
      {
1950 runge 204
        atom::log::Error(log_module_, "Supposed to get data but got none!");
1947 runge 205
        throw atom::exception::action_failed();
1945 runge 206
      }
207
    }
208
    else
209
    {
210
 
1952 runge 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;
1945 runge 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
 
1952 runge 236
    return handle_scope.Close(v8::Handle<v8::Value>(result_array));
1945 runge 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
 
1947 runge 256
  //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
1945 runge 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 */
1947 runge 266
    if (NULL == MySql::resources_[(ResourceId)args[0]->Uint32Value()])
1945 runge 267
    {
1947 runge 268
      throw atom::exception::missing_resource();
1945 runge 269
    }
270
 
271
 
272
    /* Select database */
1947 runge 273
    if (0 != mysql_select_db(MySql::resources_[(ResourceId)args[0]->Uint32Value()], *database))
1945 runge 274
    {
1950 runge 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();
1945 runge 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
 
1947 runge 294
  //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
1945 runge 295
 
296
  try
297
  {
298
    ATOM_VM_PLUGIN_NUM_PARAMS(1);
299
 
300
 
301
    /* Check that the resource exist */
1947 runge 302
    if (NULL == MySql::resources_[(ResourceId)args[0]->Uint32Value()])
1945 runge 303
    {
1947 runge 304
      throw atom::exception::missing_resource();
1945 runge 305
    }
306
 
307
 
308
    /* Select database */
1947 runge 309
    uint32_t number_of_rows = mysql_affected_rows(MySql::resources_[(ResourceId)args[0]->Uint32Value()]);
1945 runge 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
 
1947 runge 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__);
1945 runge 327
 
1947 runge 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
 
1945 runge 354
}; // namespace plugin
355
}; // namespace vm
356
}; // namespace atom