1 /*
2  * Copyright (c) 2015, 2021, Oracle and/or its affiliates.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License, version 2.0,
6  * as published by the Free Software Foundation.
7  *
8  * This program is also distributed with certain software (including
9  * but not limited to OpenSSL) that is licensed under separate terms,
10  * as designated in a particular file or component or in included license
11  * documentation.  The authors of MySQL hereby grant you an additional
12  * permission to link the program and your derivative works with the
13  * separately licensed software that they have included with MySQL.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License, version 2.0, for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23  * 02110-1301  USA
24  */
25 
26 #ifndef XPL_SQL_DATA_CONTEXT_H_
27 #define XPL_SQL_DATA_CONTEXT_H_
28 
29 #include "ngs_common/connection_type.h"
30 #include "ngs/protocol_encoder.h"
31 
32 #include "mysql/service_my_snprintf.h"
33 #include "mysql/service_command.h"
34 
35 #include "buffering_command_delegate.h"
36 #include "streaming_command_delegate.h"
37 
38 // Use an internal MySQL server user
39 #define MYSQL_SESSION_USER "mysql.session"
40 #define MYSQLXSYS_HOST "localhost"
41 #define MYSQLXSYS_ACCOUNT "'" MYSQL_SESSION_USER "'@'" MYSQLXSYS_HOST "'"
42 
43 
44 namespace ngs
45 {
46   class IOptions_session;
47   typedef ngs::shared_ptr<IOptions_session> IOptions_session_ptr;
48   class Protocol_encoder;
49 }  // namespace ngs
50 
51 
52 namespace xpl
53 {
54 
55 typedef ngs::function<bool (const std::string &password_hash)> On_user_password_hash;
56 typedef Buffering_command_delegate::Field_value Field_value;
57 typedef Buffering_command_delegate::Row_data    Row_data;
58 
59 
60 class Sql_data_context
61 {
62 public:
63   struct Result_info
64   {
65     uint64_t affected_rows;
66     uint64_t last_insert_id;
67     uint32_t num_warnings;
68     std::string message;
69     uint32_t server_status;
70 
Result_infoResult_info71     Result_info()
72     : affected_rows(0),
73       last_insert_id(0),
74       num_warnings(0),
75       server_status(0)
76     {}
77   };
78 
79   Sql_data_context(ngs::Protocol_encoder *proto, const bool query_without_authentication = false)
m_proto(proto)80   : m_proto(proto), m_mysql_session(NULL),
81     m_streaming_delegate(m_proto),
82     m_last_sql_errno(0),
83     m_auth_ok(false),
84     m_query_without_authentication(query_without_authentication),
85     m_password_expired(false)
86   {}
87 
88   virtual ~Sql_data_context();
89 
90   ngs::Error_code init();
91   ngs::Error_code init(const int client_port, const ngs::Connection_type type);
92   void            deinit();
93 
94   virtual ngs::Error_code authenticate(const char *user, const char *host, const char *ip, const char *db, On_user_password_hash password_hash_cb, bool allow_expired_passwords, ngs::IOptions_session_ptr &options_session, const ngs::Connection_type type);
95 
proto()96   ngs::Protocol_encoder &proto() { return *m_proto; }
mysql_session()97   MYSQL_SESSION mysql_session() const { return m_mysql_session; }
98 
99   uint64_t mysql_session_id() const;
100   MYSQL_THD get_thd() const;
101 
102   void detach();
103 
104   ngs::Error_code set_connection_type(const ngs::Connection_type type);
105   bool kill();
106   bool is_killed();
107   bool is_acl_disabled();
108   bool is_api_ready();
109 
110   bool wait_api_ready(ngs::function<bool()> exiting);
password_expired()111   bool password_expired() const { return m_password_expired; }
112 
113   // Get data which are parts of the string printed by
114   // USER() function
115   std::string get_user_name() const;
116   std::string get_host_or_ip() const;
117 
118   // Get data which are part of string printed by
119   // CURRENT_USER() function
120   std::string get_authenticated_user_name() const;
121   std::string get_authenticated_user_host() const;
122   bool        has_authenticated_user_a_super_priv() const;
123 
124   void switch_to_local_user(const std::string &username);
125 
126   ngs::Error_code execute_kill_sql_session(uint64_t mysql_session_id);
127 
128   // can only be executed once authenticated
129   virtual ngs::Error_code execute_sql_no_result(const char *sql, std::size_t sql_len, Result_info &r_info);
130   virtual ngs::Error_code execute_sql_and_collect_results(const char *sql, std::size_t sql_len,
131                                                           std::vector<Command_delegate::Field_type> &r_types,
132                                                           Buffering_command_delegate::Resultset &r_rows,
133                                                           Result_info &r_info);
134   virtual ngs::Error_code execute_sql_and_process_results(const char *sql, std::size_t sql_len,
135                                                           const Callback_command_delegate::Start_row_callback &start_row,
136                                                           const Callback_command_delegate::End_row_callback &end_row,
137                                                           Result_info &r_info);
138   virtual ngs::Error_code execute_sql_and_stream_results(const char *sql, std::size_t sql_len,
139                                                          bool compact_metadata, Result_info &r_info);
140 
141 private:
142   Sql_data_context(const Sql_data_context &);
143   Sql_data_context &operator=(const Sql_data_context &);
144 
145   ngs::Error_code execute_sql(Command_delegate &deleg, const char *sql, size_t length, Result_info &r_info);
146 
147   ngs::Error_code switch_to_user(const char *username, const char *hostname, const char *address, const char *db);
148 
149   static void default_completion_handler(void *ctx, unsigned int sql_errno, const char *err_msg);
150 
151   std::string m_username;
152   std::string m_hostname;
153   std::string m_address;
154   std::string m_db;
155 
156   ngs::Protocol_encoder *m_proto;
157   MYSQL_SESSION          m_mysql_session;
158 
159   Callback_command_delegate m_callback_delegate;
160   Buffering_command_delegate m_buffering_delegate;
161   Streaming_command_delegate m_streaming_delegate;
162 
163   int m_last_sql_errno;
164   std::string m_last_sql_error;
165 
166   bool m_auth_ok;
167   bool m_query_without_authentication;
168   bool m_password_expired;
169 };
170 
171 } // namespace xpl
172 
173 #undef MYSQL_CLIENT
174 
175 #endif // XPL_SQL_DATA_CONTEXT_H_
176