Subversion Repositories HomeAutomation

Rev

Rev 1947 | Go to most recent revision | 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
  {
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 */
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
 
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
 
1947 runge 261
  //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
1945 runge 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 */
1947 runge 271
    if (NULL == MySql::resources_[(ResourceId)args[0]->Uint32Value()])
1945 runge 272
    {
1947 runge 273
      throw atom::exception::missing_resource();
1945 runge 274
    }
275
 
276
 
277
    /* Select database */
1947 runge 278
    if (0 != mysql_select_db(MySql::resources_[(ResourceId)args[0]->Uint32Value()], *database))
1945 runge 279
    {
1950 runge 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();
1945 runge 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
 
1947 runge 299
  //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
1945 runge 300
 
301
  try
302
  {
303
    ATOM_VM_PLUGIN_NUM_PARAMS(1);
304
 
305
 
306
    /* Check that the resource exist */
1947 runge 307
    if (NULL == MySql::resources_[(ResourceId)args[0]->Uint32Value()])
1945 runge 308
    {
1947 runge 309
      throw atom::exception::missing_resource();
1945 runge 310
    }
311
 
312
 
313
    /* Select database */
1947 runge 314
    uint32_t number_of_rows = mysql_affected_rows(MySql::resources_[(ResourceId)args[0]->Uint32Value()]);
1945 runge 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
 
1947 runge 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__);
1945 runge 332
 
1947 runge 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
 
1945 runge 359
}; // namespace plugin
360
}; // namespace vm
361
}; // namespace atom