1 // This may look like C code, but it's really -*- C++ -*-
2 /*
3  * Copyright (C) 2008 Emweb bv, Herent, Belgium.
4  *
5  * See the LICENSE file for terms of use.
6  *
7  * Contributed by: Paul Harrison
8  */
9 #ifndef WT_DBO_BACKEND_MYSQL_H_
10 #define WT_DBO_BACKEND_MYSQL_H_
11 
12 #include <Wt/Dbo/SqlConnection.h>
13 #include <Wt/Dbo/SqlStatement.h>
14 #include <Wt/Dbo/backend/WDboMySQLDllDefs.h>
15 
16 namespace Wt {
17   namespace Dbo {
18     namespace backend {
19 
20 class MySQL_impl;
21 
22 /*! \class MySQL Wt/Dbo/backend/MySQL.h
23  *  \brief A MySQL connection
24  *
25  * This class provides the backend implementation for mariadb databases.
26  * It has been tested against MySQL 5.6.
27  *
28  * In order to work properly with Wt::Dbo, MySQL must be configured with
29  * InnoDB (for MySQL) or XtraDB (for mariadb) as the default database
30  * engine - so that the transaction based functionality works.
31  *
32  * \note There is a bug in the implementation of milliseconds in mariadb C
33  *       client which affects WTime and posix::time_duration values -- it
34  *       goes berserk when fractional part = 0.
35  *
36  * \ingroup dbo
37  */
38 class WTDBOMYSQL_API MySQL : public SqlConnection
39 {
40 public:
41   /*! \brief Opens a new MySQL backend connection.
42    *
43    *  For the connection parameter description, please refer to the
44    *  connect() method.
45    *
46    *  \param fractionalSecondsPart The number of fractional units (0 to 6).
47    *         A value of -1 indicates that the fractional part is not stored.
48    *         Fractional seconds part are supported for MySQL 5.6.4
49    *         http://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html
50    */
51   MySQL(const std::string &db, const std::string &dbuser="root",
52         const std::string &dbpasswd="", const std::string dbhost="localhost",
53         unsigned int dbport = 0,
54         const std::string &dbsocket ="/var/run/mysqld/mysqld.sock",
55         int fractionalSecondsPart = -1);
56 
57   /*! \brief Copies a MySQL connection.
58    *
59    * This creates a new connection with the same settings as another
60    * connection.
61    *
62    * \sa clone()
63    */
64   MySQL(const MySQL& other);
65 
66   /*! \brief Destructor.
67    *
68    * Closes the connection.
69    */
70   ~MySQL();
71 
72   /*! \brief Returns a copy of the connection.
73    */
74   virtual std::unique_ptr<SqlConnection> clone() const override;
75 
76   /*! \brief Tries to connect.
77    *
78    *  \param db The database name.
79    *  \param dbuser The username for the database connection -
80    *         defaults to "root".
81    *  \param dbpasswd The password for the database conection - defaults to an
82    *         empty string.
83    *  \param dbhost The hostname of the database - defaults to localhost.
84    *  \param dbport The portnumber - defaults to a default port.
85    *  \param dbsocket The socket to use.
86    *
87    * Throws an exception if there was a problem, otherwise true.
88    */
89   bool connect(const std::string &db, const std::string &dbuser="root",
90         const std::string &dbpasswd="", const std::string &dbhost="localhost",
91         unsigned int dbport = 0,
92         const std::string &dbsocket ="/var/run/mysqld/mysqld.sock");
93 
94   /*! \brief Returns the underlying connection.
95    */
connection()96   MySQL_impl *connection() { return impl_; }
97 
98   void checkConnection();
99 
100   virtual void executeSql(const std::string &sql) override;
101 
102   virtual void startTransaction() override;
103   virtual void commitTransaction() override;
104   virtual void rollbackTransaction() override;
105 
106   virtual std::unique_ptr<SqlStatement> prepareStatement(const std::string& sql) override;
107 
108   /** @name Methods that return dialect information
109    */
110   //!@{
111   virtual std::string autoincrementSql() const override;
112   virtual std::string autoincrementType() const override;
113   virtual std::string autoincrementInsertSuffix(const std::string& id) const override;
114   virtual std::vector<std::string>
115     autoincrementCreateSequenceSql(const std::string &table,
116                                    const std::string &id) const override;
117   virtual std::vector<std::string>
118     autoincrementDropSequenceSql(const std::string &table,
119                                  const std::string &id) const override;
120 
121   virtual const char *dateTimeType(SqlDateTimeType type) const override;
122   virtual const char *blobType() const override;
123   virtual bool supportAlterTable() const override;
124   virtual const char *alterTableConstraintString() const override;
requireSubqueryAlias()125   virtual bool requireSubqueryAlias() const override {return true;}
126   //!@}
127 
128   /*! \brief Returns the supported fractional seconds part
129   *
130   * By default return -1: fractional part is not stored.
131   * Fractional seconds part is supported for MySQL 5.6.4
132   * http://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html
133   *
134   * \sa setFractionalSecondsPart()
135   */
136   int getFractionalSecondsPart() const;
137 
138   /*! \brief Set the supported fractional seconds part
139   *
140   * The fractional seconds part can be also set in the constructor
141   * Fractional seconds part is supported for MySQL 5.6.4
142   * http://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html
143   *
144   * \param fractionalSecondsPart Must be in the range 0 to 6.
145   *
146   * \sa setFractionalSecondsPart()
147   */
148   void setFractionalSecondsPart(int fractionalSecondsPart);
149 
150 private:
151   std::string dbname_;
152   std::string dbuser_;
153   std::string dbpasswd_;
154   std::string dbhost_;
155   std::string dbsocket_;
156   unsigned int dbport_;
157 
158   int fractionalSecondsPart_;
159   std::string dateType_, timeType_;
160 
161   MySQL_impl* impl_; // MySQL connection handle
162 
163   void init();
164 };
165 
166     }
167   }
168 }
169 
170 #endif // WT_DBO_BACKEND_MYSQL_H_
171