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 along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23  */
24 
25 #include "view_statement_builder.h"
26 #include "ngs_common/protocol_protobuf.h"
27 #include "xpl_error.h"
28 
29 namespace xpl {
30 
31 template <typename M>
build_common(const M & msg) const32 void View_statement_builder::build_common(const M &msg) const {
33   if (!msg.has_stmt())
34     throw ngs::Error_code(ER_X_INVALID_ARGUMENT, "The field that defines the select statement is required");
35 
36   if (msg.has_algorithm()) add_algorithm(msg.algorithm());
37   if (msg.has_definer()) add_definer(msg.definer());
38   if (msg.has_security()) add_sql_security(msg.security());
39   m_builder.put("VIEW ");
40   add_collection(msg.collection());
41   if (msg.column_size() > 0) add_columns(msg.column());
42   m_builder.put(" AS ");
43   add_stmt(msg.stmt());
44   if (msg.has_check()) add_check_option(msg.check());
45 }
46 
build(const View_create & msg) const47 void View_statement_builder::build(const View_create &msg) const {
48   m_builder.put("CREATE ");
49   if (msg.has_replace_existing() && msg.replace_existing())
50     m_builder.put("OR REPLACE ");
51   build_common(msg);
52 }
53 
build(const View_modify & msg) const54 void View_statement_builder::build(const View_modify &msg) const {
55   m_builder.put("ALTER ");
56   build_common(msg);
57 }
58 
build(const View_drop & msg) const59 void View_statement_builder::build(const View_drop &msg) const {
60   m_builder.put("DROP VIEW ");
61   if (msg.has_if_exists() && msg.if_exists())
62     m_builder.put("IF EXISTS ");
63   add_collection(msg.collection());
64 }
65 
add_definer(const std::string & definer) const66 void View_statement_builder::add_definer(const std::string &definer) const {
67   if (definer.empty()) return;
68 
69   m_builder.put("DEFINER=");
70   std::string::size_type p = definer.find("@");
71   if (p == std::string::npos)
72     m_builder.put_quote(definer).put(" ");
73   else
74     m_builder.put_quote(definer.substr(0, p))
75         .put("@")
76         .put_quote(definer.substr(p + 1))
77         .put(" ");
78 }
79 
add_algorithm(const Algorithm & algorithm) const80 void View_statement_builder::add_algorithm(const Algorithm &algorithm) const {
81   m_builder.put("ALGORITHM=");
82   switch (algorithm) {
83     case Mysqlx::Crud::UNDEFINED:
84       m_builder.put("UNDEFINED ");
85       break;
86 
87     case Mysqlx::Crud::MERGE:
88       m_builder.put("MERGE ");
89       break;
90 
91     case Mysqlx::Crud::TEMPTABLE:
92       m_builder.put("TEMPTABLE ");
93       break;
94 
95     default:
96       assert("Unknown ALGORITHM type");
97   }
98 }
99 
add_sql_security(const Sql_security & security) const100 void View_statement_builder::add_sql_security(const Sql_security &security)
101     const {
102   m_builder.put("SQL SECURITY ");
103   switch (security) {
104     case Mysqlx::Crud::DEFINER:
105       m_builder.put("DEFINER ");
106       break;
107 
108     case Mysqlx::Crud::INVOKER:
109       m_builder.put("INVOKER ");
110       break;
111 
112     default:
113       assert("Unknown SECURITY type");
114   }
115 }
116 
add_check_option(const Check_option & option) const117 void View_statement_builder::add_check_option(const Check_option &option)
118     const {
119   m_builder.put(" WITH ");
120 
121   switch (option) {
122     case Mysqlx::Crud::CASCADED:
123       m_builder.put("CASCADED");
124       break;
125 
126     case Mysqlx::Crud::LOCAL:
127       m_builder.put("LOCAL");
128       break;
129 
130     default:
131       assert("Unknown CHECK type");
132   }
133   m_builder.put(" CHECK OPTION");
134 }
135 
add_columns(const Column_list & columns) const136 void View_statement_builder::add_columns(const Column_list &columns) const {
137   m_builder.put(" (").put_list(columns, &Generator::put_identifier).put(")");
138 }
139 
add_stmt(const Find & find) const140 void View_statement_builder::add_stmt(const Find &find) const {
141   Expression_generator gen(m_builder.m_qb, find.args(),
142                            find.collection().schema(),
143                            is_table_data_model(find));
144   Find_statement_builder(gen).build(find);
145 }
146 }  // namespace xpl
147