Subversion Repositories HomeAutomation

Rev

Rev 1945 | Rev 1950 | 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
    {
1947 runge 192
      throw atom::exception::action_failed();
1945 runge 193
    }
194
 
195
 
196
    /* Get the result */
1947 runge 197
    result = mysql_store_result(MySql::resources_[(ResourceId)args[0]->Uint32Value()]);
1945 runge 198
 
199
    if (NULL == result)
200
    {
1947 runge 201
      if (mysql_field_count(MySql::resources_[(ResourceId)args[0]->Uint32Value()]) > 0)
1945 runge 202
      {
1947 runge 203
        throw atom::exception::action_failed();
1945 runge 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
 
1947 runge 259
  //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
1945 runge 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 */
1947 runge 269
    if (NULL == MySql::resources_[(ResourceId)args[0]->Uint32Value()])
1945 runge 270
    {
1947 runge 271
      throw atom::exception::missing_resource();
1945 runge 272
    }
273
 
274
 
275
    /* Select database */
1947 runge 276
    if (0 != mysql_select_db(MySql::resources_[(ResourceId)args[0]->Uint32Value()], *database))
1945 runge 277
    {
1947 runge 278
       throw atom::exception::action_failed();
1945 runge 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
 
1947 runge 296
  //atom::log::Debug(log_module_, "%s called!", __FUNCTION__);
1945 runge 297
 
298
  try
299
  {
300
    ATOM_VM_PLUGIN_NUM_PARAMS(1);
301
 
302
 
303
    /* Check that the resource exist */
1947 runge 304
    if (NULL == MySql::resources_[(ResourceId)args[0]->Uint32Value()])
1945 runge 305
    {
1947 runge 306
      throw atom::exception::missing_resource();
1945 runge 307
    }
308
 
309
 
310
    /* Select database */
1947 runge 311
    uint32_t number_of_rows = mysql_affected_rows(MySql::resources_[(ResourceId)args[0]->Uint32Value()]);
1945 runge 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
 
1947 runge 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__);
1945 runge 329
 
1947 runge 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
 
1945 runge 356
}; // namespace plugin
357
}; // namespace vm
358
}; // namespace atom