File: wb_fabric_interface.cpp

package info (click to toggle)
mysql-workbench 6.3.8%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 113,932 kB
  • ctags: 87,814
  • sloc: ansic: 955,521; cpp: 427,465; python: 59,728; yacc: 59,129; xml: 54,204; sql: 7,091; objc: 965; makefile: 638; sh: 613; java: 237; perl: 30; ruby: 6; php: 1
file content (143 lines) | stat: -rw-r--r-- 4,413 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of the
* License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301  USA
*/

#include "wb_fabric_interface.h"
#include "base/string_utilities.h"

#include <stdexcept>


GRT_MODULE_ENTRY_POINT(WbFabricInterfaceImpl);

int WbFabricInterfaceImpl::openConnection(const db_mgmt_ConnectionRef &conn, const grt::StringRef &password)
{
  int new_connection_id = -1;

  MYSQL mysql;

  mysql_init(&mysql);

  // Retrieves the parameters needed to perform the connection
  std::string user = conn->parameterValues().get_string("userName");
  std::string host = conn->parameterValues().get_string("hostName");
  std::string socket = conn->parameterValues().get_string("socket");
  int port = (int)conn->parameterValues().get_int("port");

  // If the port is not specified it will take the default port to perform
  // fabric connections using mysqlrpc.
  if (port <= 0)
    port = 32275;

  // Sets the options needed to connect to the fabric server.
  int proto = MYSQL_PROTOCOL_TCP;
  mysql_options(&mysql, MYSQL_OPT_PROTOCOL, &proto);

  // Sets the connection timeout
  grt::DictRef wb_options = grt::DictRef::cast_from(get_grt()->get("/wb/options/options"));
  int connect_timeout = (int)wb_options.get_int("Fabric:ConnectionTimeOut", 60);
  mysql_options(&mysql, MYSQL_OPT_CONNECT_TIMEOUT, &connect_timeout);
  
  
  if (!mysql_real_connect(&mysql, host.c_str(), user.c_str(), password.c_str(), NULL, port, socket.c_str(),
    CLIENT_COMPRESS | CLIENT_MULTI_RESULTS))
  {
    throw std::runtime_error(mysql_error(&mysql));
  }

  // A new connection_id is created and will be returned, the actuall connection
  // will be stored here and used through the generated id.
  new_connection_id = ++_connection_id;
  _connections[new_connection_id] = mysql;


  // Changes the format of the execution results to JSON
  // This saves the burden on having to parse the output in C code
  // and allows taking advantage of the JSON loader in python
  execute(new_connection_id, "set format=json");

  return new_connection_id;
}

std::string WbFabricInterfaceImpl::execute(int connection_id, const std::string& query)
{
  int error = 0;
  std::string output;
  if (_connections.find(connection_id) != _connections.end())
  {
    error = mysql_query(&_connections[connection_id], query.c_str());

    if (!error)
    {
      MYSQL_RES *result = mysql_store_result(&_connections[connection_id]);

      // Since output is created in JSON format, a single string record
      // contains all the needed data
      if (result)
      {
        MYSQL_ROW row = mysql_fetch_row(result);

        output = row[0];

        mysql_free_result(result);
      }

      // If there are no results we need to check that it is correct to not
      // have any, else it means an error occurred
      else
        error = mysql_field_count(&_connections[connection_id]);
    }
    if (error != 0)
    {
      // Escape strings to create valid JSON structure
      std::string formatted(query);
      size_t index = 0;
      do
      {
        index = formatted.find("\"", index);
        if (index != std::string::npos)
        {
          formatted.insert(index, "\\");
          index += 2;
        }
      } while (index != std::string::npos);

      output = base::strfmt("[[{\"message\":\"SQL Error executing %s: %d - %s\"}]]", formatted.c_str(), mysql_errno(&_connections[connection_id]), mysql_error(&_connections[connection_id]));
    }
  }
  else
    output = "[[{\"message\":\"Invalid Connection Id\"}]]";

  return output;
}

int WbFabricInterfaceImpl::closeConnection(int connection_id)
{
  if (_connections.find(connection_id) != _connections.end())
  {
    mysql_close(&_connections[connection_id]);

    _connections.erase(connection_id);
  }

  return 0;
}