mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Moved mysql/mariadb connector over here.
This commit is contained in:
parent
2e683a4b69
commit
5e16f32ed3
@ -27,6 +27,10 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(sqlpp11 VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
### Project Wide Setup
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
||||
|
||||
option(MARIADB_CONNECTOR "Build MariaDB Connector" OFF)
|
||||
option(MYSQL_CONNECTOR "Build MySQL Connector" OFF)
|
||||
option(POSTGRESQL_CONNECTOR "Build PostgreSQL Connector" OFF)
|
||||
option(SQLITE3_CONNECTOR "Build SQLite3 Connector" OFF)
|
||||
@ -38,6 +42,12 @@ else()
|
||||
message(STATUS "Not building MYSQL_CONNECTOR")
|
||||
endif()
|
||||
|
||||
if(MARIADB_CONNECTOR)
|
||||
find_package(MariaDB REQUIRED)
|
||||
else()
|
||||
message(STATUS "Not building MARIAB_CONNECTOR")
|
||||
endif()
|
||||
|
||||
if(POSTGRESQL_CONNECTOR)
|
||||
find_package(PostgreSQL REQUIRED)
|
||||
else()
|
||||
@ -56,9 +66,6 @@ else()
|
||||
message(STATUS "Not building SQLCIPHER_CONNECTOR")
|
||||
endif()
|
||||
|
||||
### Project Wide Setup
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
||||
|
||||
include(CTest)
|
||||
|
||||
option(USE_SYSTEM_DATE "\
|
||||
|
35
cmake/FindMariaDB.cmake
Normal file
35
cmake/FindMariaDB.cmake
Normal file
@ -0,0 +1,35 @@
|
||||
# FindMySQL.cmake
|
||||
|
||||
if(DEFINED MSVC)
|
||||
find_path(MySQL_INCLUDE_DIR
|
||||
NAMES mariadb_version.h
|
||||
PATH_SUFFIXES include
|
||||
)
|
||||
find_library(MySQL_LIBRARY
|
||||
NAMES libmariadb
|
||||
PATH_SUFFIXES lib
|
||||
)
|
||||
else()
|
||||
find_path(MySQL_INCLUDE_DIR
|
||||
NAMES mariadb_version.h
|
||||
PATH_SUFFIXES mariadb mysql
|
||||
)
|
||||
find_library(MySQL_LIBRARY NAMES mariadb)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(
|
||||
MySQL
|
||||
MySQL_INCLUDE_DIR
|
||||
MySQL_LIBRARY
|
||||
)
|
||||
|
||||
if(MySQL_FOUND AND NOT TARGET MySQL::MySQL)
|
||||
add_library(MySQL::MySQL UNKNOWN IMPORTED)
|
||||
target_include_directories(MySQL::MySQL INTERFACE "${MySQL_INCLUDE_DIR}")
|
||||
set_target_properties(MySQL::MySQL PROPERTIES
|
||||
IMPORTED_LOCATION "${MySQL_LIBRARY}"
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "C")
|
||||
endif()
|
||||
|
||||
mark_as_advanced(MySQL_INCLUDE_DIR MySQL_LIBRARY)
|
45
cmake/FindMySQL.cmake
Normal file
45
cmake/FindMySQL.cmake
Normal file
@ -0,0 +1,45 @@
|
||||
# FindMySQL.cmake
|
||||
|
||||
if(DEFINED MSVC)
|
||||
set(SEARCH_PATHS
|
||||
"$ENV{ProgramFiles}/MySQL/MySQL Server 8.0"
|
||||
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.7"
|
||||
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.6"
|
||||
"$ENV{ProgramFiles\(x86\)}/MySQL/MySQL Server 8.0"
|
||||
"$ENV{ProgramFiles\(x86\)}/MySQL/MySQL Server 5.7"
|
||||
"$ENV{ProgramFiles\(x86\)}/MySQL/MySQL Server 5.6"
|
||||
)
|
||||
find_path(MySQL_INCLUDE_DIR
|
||||
NAMES mysql_version.h
|
||||
PATHS ${SEARCH_PATHS}
|
||||
PATH_SUFFIXES include
|
||||
)
|
||||
find_library(MySQL_LIBRARY
|
||||
NAMES libmysql
|
||||
PATHS ${SEARCH_PATHS}
|
||||
PATH_SUFFIXES lib
|
||||
)
|
||||
else()
|
||||
find_path(MySQL_INCLUDE_DIR
|
||||
NAMES mysql_version.h
|
||||
PATH_SUFFIXES mysql
|
||||
)
|
||||
find_library(MySQL_LIBRARY NAMES mysqlclient mysqlclient_r)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(
|
||||
MySQL
|
||||
MySQL_INCLUDE_DIR
|
||||
MySQL_LIBRARY
|
||||
)
|
||||
|
||||
if(MySQL_FOUND AND NOT TARGET MySQL::MySQL)
|
||||
add_library(MySQL::MySQL UNKNOWN IMPORTED)
|
||||
target_include_directories(MySQL::MySQL INTERFACE "${MySQL_INCLUDE_DIR}")
|
||||
set_target_properties(MySQL::MySQL PROPERTIES
|
||||
IMPORTED_LOCATION "${MySQL_LIBRARY}"
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "C")
|
||||
endif()
|
||||
|
||||
mark_as_advanced(MySQL_INCLUDE_DIR MySQL_LIBRARY)
|
BIN
include/sqlpp11/mysql/.serializer.h.swp
Normal file
BIN
include/sqlpp11/mysql/.serializer.h.swp
Normal file
Binary file not shown.
126
include/sqlpp11/mysql/bind_result.h
Normal file
126
include/sqlpp11/mysql/bind_result.h
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SQLPP_MYSQL_BIND_RESULT_H
|
||||
#define SQLPP_MYSQL_BIND_RESULT_H
|
||||
|
||||
#include <memory>
|
||||
#include <sqlpp11/chrono.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct prepared_statement_handle_t;
|
||||
}
|
||||
|
||||
class bind_result_t
|
||||
{
|
||||
std::shared_ptr<detail::prepared_statement_handle_t> _handle;
|
||||
void* _result_row_address = nullptr;
|
||||
|
||||
public:
|
||||
bind_result_t() = default;
|
||||
bind_result_t(const std::shared_ptr<detail::prepared_statement_handle_t>& handle);
|
||||
bind_result_t(const bind_result_t&) = delete;
|
||||
bind_result_t(bind_result_t&& rhs) = default;
|
||||
bind_result_t& operator=(const bind_result_t&) = delete;
|
||||
bind_result_t& operator=(bind_result_t&&) = default;
|
||||
~bind_result_t();
|
||||
|
||||
bool operator==(const bind_result_t& rhs) const
|
||||
{
|
||||
return _handle == rhs._handle;
|
||||
}
|
||||
|
||||
template <typename ResultRow>
|
||||
void next(ResultRow& result_row)
|
||||
{
|
||||
if (_invalid())
|
||||
{
|
||||
result_row._invalidate();
|
||||
return;
|
||||
}
|
||||
|
||||
if (&result_row != _result_row_address)
|
||||
{
|
||||
result_row._bind(*this); // sets row data to mysql bind data
|
||||
bind_impl(); // binds mysql statement to data
|
||||
_result_row_address = &result_row;
|
||||
}
|
||||
if (next_impl())
|
||||
{
|
||||
if (not result_row)
|
||||
{
|
||||
result_row._validate();
|
||||
}
|
||||
result_row._post_bind(*this); // translates bind_data to row data where required
|
||||
}
|
||||
else
|
||||
{
|
||||
if (result_row)
|
||||
result_row._invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
bool _invalid() const;
|
||||
|
||||
void _bind_boolean_result(size_t index, signed char* value, bool* is_null);
|
||||
void _bind_floating_point_result(size_t index, double* value, bool* is_null);
|
||||
void _bind_integral_result(size_t index, int64_t* value, bool* is_null);
|
||||
void _bind_unsigned_integral_result(size_t index, uint64_t* value, bool* is_null);
|
||||
void _bind_text_result(size_t index, const char** text, size_t* len);
|
||||
void _bind_blob_result(size_t index, const char** text, size_t* len);
|
||||
void _bind_date_result(size_t index, ::sqlpp::chrono::day_point* value, bool* is_null);
|
||||
void _bind_date_time_result(size_t index, ::sqlpp::chrono::microsecond_point* value, bool* is_null);
|
||||
|
||||
void _post_bind_boolean_result(size_t /* index */, signed char* /* value */, bool* /* is_null */)
|
||||
{
|
||||
}
|
||||
void _post_bind_floating_point_result(size_t /* index */, double* /* value */, bool* /* is_null */)
|
||||
{
|
||||
}
|
||||
void _post_bind_integral_result(size_t /* index */, int64_t* /* value */, bool* /* is_null */)
|
||||
{
|
||||
}
|
||||
void _post_bind_unsigned_integral_result(size_t /* index */, uint64_t* /* value */, bool* /* is_null */)
|
||||
{
|
||||
}
|
||||
void _post_bind_text_result(size_t /* index */, const char** /* text */, size_t* /* len */)
|
||||
{
|
||||
}
|
||||
void _post_bind_date_result(size_t index, ::sqlpp::chrono::day_point* value, bool* is_null);
|
||||
void _post_bind_date_time_result(size_t index, ::sqlpp::chrono::microsecond_point* value, bool* is_null);
|
||||
|
||||
private:
|
||||
void bind_impl();
|
||||
bool next_impl();
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
138
include/sqlpp11/mysql/char_result.h
Normal file
138
include/sqlpp11/mysql/char_result.h
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SQLPP_MYSQL_CHAR_RESULT_H
|
||||
#define SQLPP_MYSQL_CHAR_RESULT_H
|
||||
|
||||
#include <ciso646>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <sqlpp11/chrono.h>
|
||||
#include <sqlpp11/exception.h>
|
||||
#include <sqlpp11/mysql/char_result_row.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct result_handle;
|
||||
}
|
||||
|
||||
class char_result_t
|
||||
{
|
||||
std::unique_ptr<detail::result_handle> _handle;
|
||||
char_result_row_t _char_result_row;
|
||||
|
||||
public:
|
||||
char_result_t();
|
||||
char_result_t(std::unique_ptr<detail::result_handle>&& handle);
|
||||
char_result_t(const char_result_t&) = delete;
|
||||
char_result_t(char_result_t&& rhs);
|
||||
char_result_t& operator=(const char_result_t&) = delete;
|
||||
char_result_t& operator=(char_result_t&&);
|
||||
~char_result_t();
|
||||
|
||||
bool operator==(const char_result_t& rhs) const
|
||||
{
|
||||
return _handle == rhs._handle;
|
||||
}
|
||||
|
||||
template <typename ResultRow>
|
||||
void next(ResultRow& result_row)
|
||||
{
|
||||
if (_invalid())
|
||||
{
|
||||
result_row._invalidate();
|
||||
return;
|
||||
}
|
||||
|
||||
if (next_impl())
|
||||
{
|
||||
if (not result_row)
|
||||
{
|
||||
result_row._validate();
|
||||
}
|
||||
result_row._bind(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (result_row)
|
||||
result_row._invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
bool _invalid() const;
|
||||
|
||||
void _bind_boolean_result(size_t index, signed char* value, bool* is_null)
|
||||
{
|
||||
*is_null = (_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr);
|
||||
*value =
|
||||
(*is_null ? false : (_char_result_row.data[index][0] == 't' or _char_result_row.data[index][0] == '1'));
|
||||
}
|
||||
|
||||
void _bind_floating_point_result(size_t index, double* value, bool* is_null)
|
||||
{
|
||||
*is_null = (_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr);
|
||||
*value = (*is_null ? 0 : std::strtod(_char_result_row.data[index], nullptr));
|
||||
}
|
||||
|
||||
void _bind_integral_result(size_t index, int64_t* value, bool* is_null)
|
||||
{
|
||||
*is_null = (_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr);
|
||||
*value = (*is_null ? 0 : std::strtoll(_char_result_row.data[index], nullptr, 10));
|
||||
}
|
||||
|
||||
void _bind_unsigned_integral_result(size_t index, uint64_t* value, bool* is_null)
|
||||
{
|
||||
*is_null = (_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr);
|
||||
*value = (*is_null ? 0 : std::strtoull(_char_result_row.data[index], nullptr, 10));
|
||||
}
|
||||
|
||||
void _bind_blob_result(size_t index, const uint8_t** value, size_t* len)
|
||||
{
|
||||
bool is_null = (_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr);
|
||||
*value = (uint8_t*)(is_null ? nullptr : _char_result_row.data[index]);
|
||||
*len = (is_null ? 0 : _char_result_row.len[index]);
|
||||
}
|
||||
|
||||
void _bind_text_result(size_t index, const char** value, size_t* len)
|
||||
{
|
||||
bool is_null = (_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr);
|
||||
*value = (is_null ? nullptr : _char_result_row.data[index]);
|
||||
*len = (is_null ? 0 : _char_result_row.len[index]);
|
||||
}
|
||||
|
||||
void _bind_date_result(size_t index, ::sqlpp::chrono::day_point* value, bool* is_null);
|
||||
void _bind_date_time_result(size_t index, ::sqlpp::chrono::microsecond_point* value, bool* is_null);
|
||||
|
||||
private:
|
||||
bool next_impl();
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
47
include/sqlpp11/mysql/char_result_row.h
Normal file
47
include/sqlpp11/mysql/char_result_row.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SQLPP_MYSQL_CHAR_RESULT_ROW_H
|
||||
#define SQLPP_MYSQL_CHAR_RESULT_ROW_H
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
struct char_result_row_t
|
||||
{
|
||||
const char** data;
|
||||
unsigned long* len;
|
||||
|
||||
bool operator==(const char_result_row_t& rhs) const
|
||||
{
|
||||
return data == rhs.data && len == rhs.len;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
316
include/sqlpp11/mysql/connection.h
Normal file
316
include/sqlpp11/mysql/connection.h
Normal file
@ -0,0 +1,316 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2017, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SQLPP_MYSQL_CONNECTION_H
|
||||
#define SQLPP_MYSQL_CONNECTION_H
|
||||
|
||||
#include <sqlpp11/connection.h>
|
||||
#include <sqlpp11/mysql/bind_result.h>
|
||||
#include <sqlpp11/mysql/char_result.h>
|
||||
#include <sqlpp11/mysql/connection_config.h>
|
||||
#include <sqlpp11/mysql/prepared_statement.h>
|
||||
#include <sqlpp11/serialize.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#if LIBMYSQL_VERSION_ID < 80000
|
||||
typedef struct st_mysql MYSQL;
|
||||
#else
|
||||
struct MYSQL;
|
||||
#endif
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
struct scoped_library_initializer_t
|
||||
{
|
||||
// calls mysql_library_init
|
||||
scoped_library_initializer_t(int argc = 0, char** argv = nullptr, char** groups = nullptr);
|
||||
|
||||
// calls mysql_library_end
|
||||
~scoped_library_initializer_t();
|
||||
};
|
||||
|
||||
// This will also cleanup when the program shuts down
|
||||
void global_library_init(int argc = 0, char** argv = nullptr, char** groups = nullptr);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct connection_handle_t;
|
||||
}
|
||||
|
||||
class connection;
|
||||
|
||||
struct serializer_t
|
||||
{
|
||||
serializer_t(const connection& db) : _db(db)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::ostream& operator<<(T t)
|
||||
{
|
||||
return _os << t;
|
||||
}
|
||||
|
||||
std::string escape(std::string arg);
|
||||
|
||||
std::string str() const
|
||||
{
|
||||
return _os.str();
|
||||
}
|
||||
|
||||
const connection& _db;
|
||||
std::stringstream _os;
|
||||
};
|
||||
|
||||
std::integral_constant<char, '`'> get_quote_left(const serializer_t&);
|
||||
|
||||
std::integral_constant<char, '`'> get_quote_right(const serializer_t&);
|
||||
|
||||
class connection : public sqlpp::connection
|
||||
{
|
||||
std::unique_ptr<detail::connection_handle_t> _handle;
|
||||
bool _transaction_active = false;
|
||||
|
||||
// direct execution
|
||||
char_result_t select_impl(const std::string& statement);
|
||||
size_t insert_impl(const std::string& statement);
|
||||
size_t update_impl(const std::string& statement);
|
||||
size_t remove_impl(const std::string& statement);
|
||||
|
||||
// prepared execution
|
||||
prepared_statement_t prepare_impl(const std::string& statement, size_t no_of_parameters, size_t no_of_columns);
|
||||
bind_result_t run_prepared_select_impl(prepared_statement_t& prepared_statement);
|
||||
size_t run_prepared_insert_impl(prepared_statement_t& prepared_statement);
|
||||
size_t run_prepared_update_impl(prepared_statement_t& prepared_statement);
|
||||
size_t run_prepared_remove_impl(prepared_statement_t& prepared_statement);
|
||||
|
||||
public:
|
||||
using _prepared_statement_t = ::sqlpp::mysql::prepared_statement_t;
|
||||
using _context_t = serializer_t;
|
||||
using _serializer_context_t = _context_t;
|
||||
using _interpreter_context_t = _context_t;
|
||||
|
||||
struct _tags
|
||||
{
|
||||
using _null_result_is_trivial_value = std::true_type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static _context_t& _serialize_interpretable(const T& t, _context_t& context)
|
||||
{
|
||||
return serialize(t, context);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static _context_t& _interpret_interpretable(const T& t, _context_t& context)
|
||||
{
|
||||
return serialize(t, context);
|
||||
}
|
||||
|
||||
connection(const std::shared_ptr<connection_config>& config);
|
||||
~connection();
|
||||
connection(const connection&) = delete;
|
||||
connection& operator=(const connection&) = delete;
|
||||
connection& operator=(connection&&) = default;
|
||||
connection(connection&& other);
|
||||
|
||||
bool is_valid();
|
||||
void reconnect();
|
||||
const std::shared_ptr<connection_config> get_config();
|
||||
|
||||
bool is_transaction_active()
|
||||
{
|
||||
return _transaction_active;
|
||||
}
|
||||
template <typename Select>
|
||||
char_result_t select(const Select& s)
|
||||
{
|
||||
_context_t context(*this);
|
||||
serialize(s, context);
|
||||
return select_impl(context.str());
|
||||
}
|
||||
|
||||
template <typename Select>
|
||||
_prepared_statement_t prepare_select(Select& s)
|
||||
{
|
||||
_context_t context(*this);
|
||||
serialize(s, context);
|
||||
return prepare_impl(context.str(), s._get_no_of_parameters(), s.get_no_of_result_columns());
|
||||
}
|
||||
|
||||
template <typename PreparedSelect>
|
||||
bind_result_t run_prepared_select(const PreparedSelect& s)
|
||||
{
|
||||
s._bind_params();
|
||||
return run_prepared_select_impl(s._prepared_statement);
|
||||
}
|
||||
|
||||
//! insert returns the last auto_incremented id (or zero, if there is none)
|
||||
template <typename Insert>
|
||||
size_t insert(const Insert& i)
|
||||
{
|
||||
_context_t context(*this);
|
||||
serialize(i, context);
|
||||
return insert_impl(context.str());
|
||||
}
|
||||
|
||||
template <typename Insert>
|
||||
_prepared_statement_t prepare_insert(Insert& i)
|
||||
{
|
||||
_context_t context(*this);
|
||||
serialize(i, context);
|
||||
return prepare_impl(context.str(), i._get_no_of_parameters(), 0);
|
||||
}
|
||||
|
||||
template <typename PreparedInsert>
|
||||
size_t run_prepared_insert(const PreparedInsert& i)
|
||||
{
|
||||
i._bind_params();
|
||||
return run_prepared_insert_impl(i._prepared_statement);
|
||||
}
|
||||
|
||||
//! update returns the number of affected rows
|
||||
template <typename Update>
|
||||
size_t update(const Update& u)
|
||||
{
|
||||
_context_t context(*this);
|
||||
serialize(u, context);
|
||||
return update_impl(context.str());
|
||||
}
|
||||
|
||||
template <typename Update>
|
||||
_prepared_statement_t prepare_update(Update& u)
|
||||
{
|
||||
_context_t context(*this);
|
||||
serialize(u, context);
|
||||
return prepare_impl(context.str(), u._get_no_of_parameters(), 0);
|
||||
}
|
||||
|
||||
template <typename PreparedUpdate>
|
||||
size_t run_prepared_update(const PreparedUpdate& u)
|
||||
{
|
||||
u._bind_params();
|
||||
return run_prepared_update_impl(u._prepared_statement);
|
||||
}
|
||||
|
||||
//! remove returns the number of removed rows
|
||||
template <typename Remove>
|
||||
size_t remove(const Remove& r)
|
||||
{
|
||||
_context_t context(*this);
|
||||
serialize(r, context);
|
||||
return remove_impl(context.str());
|
||||
}
|
||||
|
||||
template <typename Remove>
|
||||
_prepared_statement_t prepare_remove(Remove& r)
|
||||
{
|
||||
_context_t context(*this);
|
||||
serialize(r, context);
|
||||
return prepare_impl(context.str(), r._get_no_of_parameters(), 0);
|
||||
}
|
||||
|
||||
template <typename PreparedRemove>
|
||||
size_t run_prepared_remove(const PreparedRemove& r)
|
||||
{
|
||||
r._bind_params();
|
||||
return run_prepared_remove_impl(r._prepared_statement);
|
||||
}
|
||||
|
||||
//! execute arbitrary command (e.g. create a table)
|
||||
void execute(const std::string& command);
|
||||
|
||||
//! escape given string (does not quote, though)
|
||||
std::string escape(const std::string& s) const;
|
||||
|
||||
//! call run on the argument
|
||||
template <typename T>
|
||||
auto run(const T& t) -> decltype(t._run(*this))
|
||||
{
|
||||
return t._run(*this);
|
||||
}
|
||||
|
||||
//! call run on the argument
|
||||
template <typename T>
|
||||
auto _run(const T& t, ::sqlpp::consistent_t) -> decltype(t._run(*this))
|
||||
{
|
||||
return t._run(*this);
|
||||
}
|
||||
|
||||
template <typename Check, typename T>
|
||||
auto _run(const T& t, Check) -> Check;
|
||||
|
||||
template <typename T>
|
||||
auto operator()(const T& t) -> decltype(this->_run(t, sqlpp::run_check_t<_serializer_context_t, T>{}))
|
||||
{
|
||||
return _run(t, sqlpp::run_check_t<_serializer_context_t, T>{});
|
||||
}
|
||||
|
||||
//! call prepare on the argument
|
||||
template <typename T>
|
||||
auto _prepare(const T& t, ::sqlpp::consistent_t) -> decltype(t._prepare(*this))
|
||||
{
|
||||
return t._prepare(*this);
|
||||
}
|
||||
|
||||
template <typename Check, typename T>
|
||||
auto _prepare(const T& t, Check) -> Check;
|
||||
|
||||
template <typename T>
|
||||
auto prepare(const T& t) -> decltype(this->_prepare(t, sqlpp::prepare_check_t<_serializer_context_t, T>{}))
|
||||
{
|
||||
return _prepare(t, sqlpp::prepare_check_t<_serializer_context_t, T>{});
|
||||
}
|
||||
|
||||
//! start transaction
|
||||
void start_transaction();
|
||||
|
||||
//! commit transaction (or throw if the transaction has been finished already)
|
||||
void commit_transaction();
|
||||
|
||||
//! rollback transaction with or without reporting the rollback (or throw if the transaction has been finished
|
||||
// already)
|
||||
void rollback_transaction(bool report);
|
||||
|
||||
//! report a rollback failure (will be called by transactions in case of a rollback failure in the destructor)
|
||||
void report_rollback_failure(const std::string message) noexcept;
|
||||
|
||||
MYSQL* get_handle();
|
||||
};
|
||||
|
||||
inline std::string serializer_t::escape(std::string arg)
|
||||
{
|
||||
return _db.escape(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <sqlpp11/mysql/serializer.h>
|
||||
|
||||
#endif
|
320
include/sqlpp11/mysql/connection.h.orig
Normal file
320
include/sqlpp11/mysql/connection.h.orig
Normal file
@ -0,0 +1,320 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2017, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SQLPP_MYSQL_CONNECTION_H
|
||||
#define SQLPP_MYSQL_CONNECTION_H
|
||||
|
||||
#include <sqlpp11/connection.h>
|
||||
#include <sqlpp11/mysql/bind_result.h>
|
||||
#include <sqlpp11/mysql/char_result.h>
|
||||
#include <sqlpp11/mysql/connection_config.h>
|
||||
#include <sqlpp11/mysql/prepared_statement.h>
|
||||
#include <sqlpp11/serialize.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
#if LIBMYSQL_VERSION_ID < 80000
|
||||
typedef struct st_mysql MYSQL;
|
||||
#else
|
||||
struct MYSQL;
|
||||
#endif
|
||||
=======
|
||||
struct MYSQL;
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
struct scoped_library_initializer_t
|
||||
{
|
||||
// calls mysql_library_init
|
||||
scoped_library_initializer_t(int argc = 0, char** argv = nullptr, char** groups = nullptr);
|
||||
|
||||
// calls mysql_library_end
|
||||
~scoped_library_initializer_t();
|
||||
};
|
||||
|
||||
// This will also cleanup when the program shuts down
|
||||
void global_library_init(int argc = 0, char** argv = nullptr, char** groups = nullptr);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct connection_handle_t;
|
||||
}
|
||||
|
||||
class connection;
|
||||
|
||||
struct serializer_t
|
||||
{
|
||||
serializer_t(const connection& db) : _db(db)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::ostream& operator<<(T t)
|
||||
{
|
||||
return _os << t;
|
||||
}
|
||||
|
||||
std::string escape(std::string arg);
|
||||
|
||||
std::string str() const
|
||||
{
|
||||
return _os.str();
|
||||
}
|
||||
|
||||
const connection& _db;
|
||||
std::stringstream _os;
|
||||
};
|
||||
|
||||
std::integral_constant<char, '`'> get_quote_left(const serializer_t&);
|
||||
|
||||
std::integral_constant<char, '`'> get_quote_right(const serializer_t&);
|
||||
|
||||
class connection : public sqlpp::connection
|
||||
{
|
||||
std::unique_ptr<detail::connection_handle_t> _handle;
|
||||
bool _transaction_active = false;
|
||||
|
||||
// direct execution
|
||||
char_result_t select_impl(const std::string& statement);
|
||||
size_t insert_impl(const std::string& statement);
|
||||
size_t update_impl(const std::string& statement);
|
||||
size_t remove_impl(const std::string& statement);
|
||||
|
||||
// prepared execution
|
||||
prepared_statement_t prepare_impl(const std::string& statement, size_t no_of_parameters, size_t no_of_columns);
|
||||
bind_result_t run_prepared_select_impl(prepared_statement_t& prepared_statement);
|
||||
size_t run_prepared_insert_impl(prepared_statement_t& prepared_statement);
|
||||
size_t run_prepared_update_impl(prepared_statement_t& prepared_statement);
|
||||
size_t run_prepared_remove_impl(prepared_statement_t& prepared_statement);
|
||||
|
||||
public:
|
||||
using _prepared_statement_t = ::sqlpp::mysql::prepared_statement_t;
|
||||
using _context_t = serializer_t;
|
||||
using _serializer_context_t = _context_t;
|
||||
using _interpreter_context_t = _context_t;
|
||||
|
||||
struct _tags
|
||||
{
|
||||
using _null_result_is_trivial_value = std::true_type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static _context_t& _serialize_interpretable(const T& t, _context_t& context)
|
||||
{
|
||||
return ::sqlpp::serialize(t, context);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static _context_t& _interpret_interpretable(const T& t, _context_t& context)
|
||||
{
|
||||
return ::sqlpp::serialize(t, context);
|
||||
}
|
||||
|
||||
connection(const std::shared_ptr<connection_config>& config);
|
||||
~connection();
|
||||
connection(const connection&) = delete;
|
||||
connection& operator=(const connection&) = delete;
|
||||
connection& operator=(connection&&) = default;
|
||||
connection(connection&& other);
|
||||
|
||||
bool is_valid();
|
||||
void reconnect();
|
||||
const std::shared_ptr<connection_config> get_config();
|
||||
|
||||
bool is_transaction_active()
|
||||
{
|
||||
return _transaction_active;
|
||||
}
|
||||
template <typename Select>
|
||||
char_result_t select(const Select& s)
|
||||
{
|
||||
_context_t context(*this);
|
||||
serialize(s, context);
|
||||
return select_impl(context.str());
|
||||
}
|
||||
|
||||
template <typename Select>
|
||||
_prepared_statement_t prepare_select(Select& s)
|
||||
{
|
||||
_context_t context(*this);
|
||||
serialize(s, context);
|
||||
return prepare_impl(context.str(), s._get_no_of_parameters(), s.get_no_of_result_columns());
|
||||
}
|
||||
|
||||
template <typename PreparedSelect>
|
||||
bind_result_t run_prepared_select(const PreparedSelect& s)
|
||||
{
|
||||
s._bind_params();
|
||||
return run_prepared_select_impl(s._prepared_statement);
|
||||
}
|
||||
|
||||
//! insert returns the last auto_incremented id (or zero, if there is none)
|
||||
template <typename Insert>
|
||||
size_t insert(const Insert& i)
|
||||
{
|
||||
_context_t context(*this);
|
||||
serialize(i, context);
|
||||
return insert_impl(context.str());
|
||||
}
|
||||
|
||||
template <typename Insert>
|
||||
_prepared_statement_t prepare_insert(Insert& i)
|
||||
{
|
||||
_context_t context(*this);
|
||||
serialize(i, context);
|
||||
return prepare_impl(context.str(), i._get_no_of_parameters(), 0);
|
||||
}
|
||||
|
||||
template <typename PreparedInsert>
|
||||
size_t run_prepared_insert(const PreparedInsert& i)
|
||||
{
|
||||
i._bind_params();
|
||||
return run_prepared_insert_impl(i._prepared_statement);
|
||||
}
|
||||
|
||||
//! update returns the number of affected rows
|
||||
template <typename Update>
|
||||
size_t update(const Update& u)
|
||||
{
|
||||
_context_t context(*this);
|
||||
serialize(u, context);
|
||||
return update_impl(context.str());
|
||||
}
|
||||
|
||||
template <typename Update>
|
||||
_prepared_statement_t prepare_update(Update& u)
|
||||
{
|
||||
_context_t context(*this);
|
||||
serialize(u, context);
|
||||
return prepare_impl(context.str(), u._get_no_of_parameters(), 0);
|
||||
}
|
||||
|
||||
template <typename PreparedUpdate>
|
||||
size_t run_prepared_update(const PreparedUpdate& u)
|
||||
{
|
||||
u._bind_params();
|
||||
return run_prepared_update_impl(u._prepared_statement);
|
||||
}
|
||||
|
||||
//! remove returns the number of removed rows
|
||||
template <typename Remove>
|
||||
size_t remove(const Remove& r)
|
||||
{
|
||||
_context_t context(*this);
|
||||
serialize(r, context);
|
||||
return remove_impl(context.str());
|
||||
}
|
||||
|
||||
template <typename Remove>
|
||||
_prepared_statement_t prepare_remove(Remove& r)
|
||||
{
|
||||
_context_t context(*this);
|
||||
serialize(r, context);
|
||||
return prepare_impl(context.str(), r._get_no_of_parameters(), 0);
|
||||
}
|
||||
|
||||
template <typename PreparedRemove>
|
||||
size_t run_prepared_remove(const PreparedRemove& r)
|
||||
{
|
||||
r._bind_params();
|
||||
return run_prepared_remove_impl(r._prepared_statement);
|
||||
}
|
||||
|
||||
//! execute arbitrary command (e.g. create a table)
|
||||
void execute(const std::string& command);
|
||||
|
||||
//! escape given string (does not quote, though)
|
||||
std::string escape(const std::string& s) const;
|
||||
|
||||
//! call run on the argument
|
||||
template <typename T>
|
||||
auto run(const T& t) -> decltype(t._run(*this))
|
||||
{
|
||||
return t._run(*this);
|
||||
}
|
||||
|
||||
//! call run on the argument
|
||||
template <typename T>
|
||||
auto _run(const T& t, ::sqlpp::consistent_t) -> decltype(t._run(*this))
|
||||
{
|
||||
return t._run(*this);
|
||||
}
|
||||
|
||||
template <typename Check, typename T>
|
||||
auto _run(const T& t, Check) -> Check;
|
||||
|
||||
template <typename T>
|
||||
auto operator()(const T& t) -> decltype(this->_run(t, sqlpp::run_check_t<_serializer_context_t, T>{}))
|
||||
{
|
||||
return _run(t, sqlpp::run_check_t<_serializer_context_t, T>{});
|
||||
}
|
||||
|
||||
//! call prepare on the argument
|
||||
template <typename T>
|
||||
auto _prepare(const T& t, ::sqlpp::consistent_t) -> decltype(t._prepare(*this))
|
||||
{
|
||||
return t._prepare(*this);
|
||||
}
|
||||
|
||||
template <typename Check, typename T>
|
||||
auto _prepare(const T& t, Check) -> Check;
|
||||
|
||||
template <typename T>
|
||||
auto prepare(const T& t) -> decltype(this->_prepare(t, sqlpp::prepare_check_t<_serializer_context_t, T>{}))
|
||||
{
|
||||
return _prepare(t, sqlpp::prepare_check_t<_serializer_context_t, T>{});
|
||||
}
|
||||
|
||||
//! start transaction
|
||||
void start_transaction();
|
||||
|
||||
//! commit transaction (or throw if the transaction has been finished already)
|
||||
void commit_transaction();
|
||||
|
||||
//! rollback transaction with or without reporting the rollback (or throw if the transaction has been finished
|
||||
// already)
|
||||
void rollback_transaction(bool report);
|
||||
|
||||
//! report a rollback failure (will be called by transactions in case of a rollback failure in the destructor)
|
||||
void report_rollback_failure(const std::string message) noexcept;
|
||||
|
||||
MYSQL* get_handle();
|
||||
};
|
||||
|
||||
inline std::string serializer_t::escape(std::string arg)
|
||||
{
|
||||
return _db.escape(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <sqlpp11/mysql/serializer.h>
|
||||
|
||||
#endif
|
66
include/sqlpp11/mysql/connection_config.h
Normal file
66
include/sqlpp11/mysql/connection_config.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SQLPP_MYSQL_CONNECTION_CONFIG_H
|
||||
#define SQLPP_MYSQL_CONNECTION_CONFIG_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
class connection;
|
||||
struct connection_config
|
||||
{
|
||||
typedef ::sqlpp::mysql::connection connection;
|
||||
std::string host = "localhost";
|
||||
std::string user;
|
||||
std::string password;
|
||||
std::string database;
|
||||
unsigned int port = 0;
|
||||
std::string unix_socket;
|
||||
unsigned long client_flag = 0;
|
||||
std::string charset = "utf8";
|
||||
bool auto_reconnect = true;
|
||||
bool debug = false;
|
||||
|
||||
bool operator==(const connection_config& other) const
|
||||
{
|
||||
return (other.host == host and other.user == user and other.password == password and
|
||||
other.database == database and other.charset == charset and other.auto_reconnect == auto_reconnect and
|
||||
other.debug == debug);
|
||||
}
|
||||
|
||||
bool operator!=(const connection_config& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
33
include/sqlpp11/mysql/mysql.h
Normal file
33
include/sqlpp11/mysql/mysql.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SQLPP_MYSQL_H
|
||||
#define SQLPP_MYSQL_H
|
||||
|
||||
#include <sqlpp11/mysql/connection.h>
|
||||
#include <sqlpp11/mysql/char_result.h>
|
||||
|
||||
#endif
|
76
include/sqlpp11/mysql/prepared_statement.h
Normal file
76
include/sqlpp11/mysql/prepared_statement.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SQLPP_MYSQL_PREPARED_STATEMENT_H
|
||||
#define SQLPP_MYSQL_PREPARED_STATEMENT_H
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <sqlpp11/chrono.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
class connection;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct prepared_statement_handle_t;
|
||||
}
|
||||
|
||||
class prepared_statement_t
|
||||
{
|
||||
friend ::sqlpp::mysql::connection;
|
||||
std::shared_ptr<detail::prepared_statement_handle_t> _handle;
|
||||
|
||||
public:
|
||||
prepared_statement_t() = delete;
|
||||
prepared_statement_t(std::shared_ptr<detail::prepared_statement_handle_t>&& handle);
|
||||
prepared_statement_t(const prepared_statement_t&) = delete;
|
||||
prepared_statement_t(prepared_statement_t&& rhs) = default;
|
||||
prepared_statement_t& operator=(const prepared_statement_t&) = delete;
|
||||
prepared_statement_t& operator=(prepared_statement_t&&) = default;
|
||||
~prepared_statement_t() = default;
|
||||
|
||||
bool operator==(const prepared_statement_t& rhs) const
|
||||
{
|
||||
return _handle == rhs._handle;
|
||||
}
|
||||
|
||||
void _pre_bind();
|
||||
|
||||
void _bind_boolean_parameter(size_t index, const signed char* value, bool is_null);
|
||||
void _bind_integral_parameter(size_t index, const int64_t* value, bool is_null);
|
||||
void _bind_unsigned_integral_parameter(size_t index, const uint64_t* value, bool is_null);
|
||||
void _bind_floating_point_parameter(size_t index, const double* value, bool is_null);
|
||||
void _bind_text_parameter(size_t index, const std::string* value, bool is_null);
|
||||
void _bind_date_parameter(size_t index, const ::sqlpp::chrono::day_point* value, bool is_null);
|
||||
void _bind_date_time_parameter(size_t index, const ::sqlpp::chrono::microsecond_point* value, bool is_null);
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
51
include/sqlpp11/mysql/serializer.h
Normal file
51
include/sqlpp11/mysql/serializer.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SQLPP_MYSQL_SERIALIZER_H
|
||||
#define SQLPP_MYSQL_SERIALIZER_H
|
||||
|
||||
#include <sqlpp11/data_types/text/concat.h>
|
||||
#include <sqlpp11/insert_value_list.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template <typename First, typename... Args>
|
||||
mysql::serializer_t& serialize(const concat_t<First, Args...>& t, mysql::serializer_t& context)
|
||||
{
|
||||
context << "CONCAT(";
|
||||
interpret_tuple(t._args, ',', context);
|
||||
context << ')';
|
||||
return context;
|
||||
}
|
||||
|
||||
inline mysql::serializer_t& serialize(const insert_default_values_data_t&, mysql::serializer_t& context)
|
||||
{
|
||||
context << " () VALUES()";
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
78
src/mysql/CMakeLists.txt
Normal file
78
src/mysql/CMakeLists.txt
Normal file
@ -0,0 +1,78 @@
|
||||
set(PUBLIC_HEADERS_DIR "${PROJECT_SOURCE_DIR}/include/")
|
||||
|
||||
add_library(sqlpp-mysql
|
||||
bind_result.cpp
|
||||
char_result.cpp
|
||||
connection.cpp
|
||||
prepared_statement.cpp
|
||||
detail/connection_handle.cpp
|
||||
)
|
||||
|
||||
target_include_directories(sqlpp-mysql PUBLIC
|
||||
$<BUILD_INTERFACE:${PUBLIC_HEADERS_DIR}>
|
||||
)
|
||||
|
||||
find_package(date REQUIRED)
|
||||
find_package(Sqlpp11 REQUIRED)
|
||||
|
||||
target_link_libraries(sqlpp-mysql PUBLIC sqlpp11::sqlpp11)
|
||||
target_link_libraries(sqlpp-mysql PRIVATE MySQL::MySQL)
|
||||
target_link_libraries(sqlpp-mysql PRIVATE date::date)
|
||||
|
||||
# Installation
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
add_library(sqlpp11::mysql ALIAS sqlpp-mysql)
|
||||
set_target_properties(sqlpp-mysql PROPERTIES EXPORT_NAME sqlpp11::mysql)
|
||||
|
||||
install(
|
||||
TARGETS sqlpp-mysql
|
||||
EXPORT sqlpp-mysql-targets
|
||||
COMPONENT sqlpp11::mysql
|
||||
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY ${PUBLIC_HEADERS_DIR}
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
COMPONENT sqlpp11::mysql
|
||||
)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
set(cmake_config_path "${CMAKE_INSTALL_LIBDIR}/cmake/sqlpp-mysql")
|
||||
|
||||
configure_package_config_file(
|
||||
sqlpp-mysql-config.cmake.in
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/sqlpp-mysql-config.cmake"
|
||||
INSTALL_DESTINATION "${cmake_config_path}"
|
||||
)
|
||||
|
||||
write_basic_package_version_file(
|
||||
sqlpp-mysql-config-version.cmake
|
||||
VERSION ${VERSION}
|
||||
COMPATIBILITY SameMajorVersion
|
||||
${extra_version_file_args}
|
||||
)
|
||||
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/sqlpp-mysql-config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/sqlpp-mysql-config-version.cmake"
|
||||
DESTINATION "${cmake_config_path}"
|
||||
COMPONENT sqlpp11::mysql
|
||||
)
|
||||
|
||||
install(FILES
|
||||
"${PROJECT_SOURCE_DIR}/cmake/FindMySQL.cmake"
|
||||
DESTINATION "${cmake_config_path}"
|
||||
COMPONENT sqlpp11::mysql
|
||||
)
|
||||
|
||||
install(
|
||||
EXPORT sqlpp-mysql-targets
|
||||
FILE sqlpp-mysql-targets.cmake
|
||||
DESTINATION "${cmake_config_path}"
|
||||
COMPONENT sqlpp11::mysql
|
||||
)
|
346
src/mysql/bind_result.cpp
Normal file
346
src/mysql/bind_result.cpp
Normal file
@ -0,0 +1,346 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2016, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "detail/prepared_statement_handle.h"
|
||||
#include <ciso646>
|
||||
#include <date/date.h>
|
||||
#include <iostream>
|
||||
#include "sqlpp_mysql.h"
|
||||
#include <sqlpp11/exception.h>
|
||||
#include <sqlpp11/mysql/bind_result.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
bind_result_t::bind_result_t(const std::shared_ptr<detail::prepared_statement_handle_t>& handle) : _handle(handle)
|
||||
{
|
||||
if (_handle and _handle->debug)
|
||||
std::cerr << "MySQL debug: Constructing bind result, using handle at " << _handle.get() << std::endl;
|
||||
}
|
||||
|
||||
bind_result_t::~bind_result_t()
|
||||
{
|
||||
if (_handle)
|
||||
mysql_stmt_free_result(_handle->mysql_stmt);
|
||||
}
|
||||
|
||||
bool bind_result_t::_invalid() const
|
||||
{
|
||||
return !_handle or !*_handle;
|
||||
}
|
||||
|
||||
void bind_result_t::_bind_boolean_result(size_t index, signed char* value, bool* is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: binding boolean result " << static_cast<void*>(value) << " at index: " << index
|
||||
<< std::endl;
|
||||
|
||||
detail::result_meta_data_t& meta_data = _handle->result_param_meta_data[index];
|
||||
meta_data.index = index;
|
||||
meta_data.len = nullptr;
|
||||
meta_data.is_null = is_null;
|
||||
|
||||
MYSQL_BIND& param = _handle->result_params[index];
|
||||
param.buffer_type = MYSQL_TYPE_TINY;
|
||||
param.buffer = value;
|
||||
param.buffer_length = sizeof(*value);
|
||||
param.length = &meta_data.bound_len;
|
||||
param.is_null = &meta_data.bound_is_null;
|
||||
param.is_unsigned = false;
|
||||
param.error = &meta_data.bound_error;
|
||||
}
|
||||
|
||||
void bind_result_t::_bind_integral_result(size_t index, int64_t* value, bool* is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: binding integral result " << static_cast<void*>(value) << " at index: " << index
|
||||
<< std::endl;
|
||||
|
||||
detail::result_meta_data_t& meta_data = _handle->result_param_meta_data[index];
|
||||
meta_data.index = index;
|
||||
meta_data.len = nullptr;
|
||||
meta_data.is_null = is_null;
|
||||
|
||||
MYSQL_BIND& param = _handle->result_params[index];
|
||||
param.buffer_type = MYSQL_TYPE_LONGLONG;
|
||||
param.buffer = value;
|
||||
param.buffer_length = sizeof(*value);
|
||||
param.length = &meta_data.bound_len;
|
||||
param.is_null = &meta_data.bound_is_null;
|
||||
param.is_unsigned = false;
|
||||
param.error = &meta_data.bound_error;
|
||||
}
|
||||
|
||||
void bind_result_t::_bind_unsigned_integral_result(size_t index, uint64_t* value, bool* is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: binding unsigned integral result " << static_cast<void*>(value)
|
||||
<< " at index: " << index << std::endl;
|
||||
|
||||
detail::result_meta_data_t& meta_data = _handle->result_param_meta_data[index];
|
||||
meta_data.index = index;
|
||||
meta_data.len = nullptr;
|
||||
meta_data.is_null = is_null;
|
||||
|
||||
MYSQL_BIND& param = _handle->result_params[index];
|
||||
param.buffer_type = MYSQL_TYPE_LONGLONG;
|
||||
param.buffer = value;
|
||||
param.buffer_length = sizeof(*value);
|
||||
param.length = &meta_data.bound_len;
|
||||
param.is_null = &meta_data.bound_is_null;
|
||||
param.is_unsigned = true;
|
||||
param.error = &meta_data.bound_error;
|
||||
}
|
||||
|
||||
void bind_result_t::_bind_floating_point_result(size_t index, double* value, bool* is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: binding floating point result " << static_cast<void*>(value)
|
||||
<< " at index: " << index << std::endl;
|
||||
|
||||
detail::result_meta_data_t& meta_data = _handle->result_param_meta_data[index];
|
||||
meta_data.index = index;
|
||||
meta_data.len = nullptr;
|
||||
meta_data.is_null = is_null;
|
||||
|
||||
MYSQL_BIND& param = _handle->result_params[index];
|
||||
param.buffer_type = MYSQL_TYPE_DOUBLE;
|
||||
param.buffer = value;
|
||||
param.buffer_length = sizeof(*value);
|
||||
param.length = &meta_data.bound_len;
|
||||
param.is_null = &meta_data.bound_is_null;
|
||||
param.is_unsigned = false;
|
||||
param.error = &meta_data.bound_error;
|
||||
}
|
||||
|
||||
void bind_result_t::_bind_text_result(size_t index, const char** value, size_t* len)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: binding text result " << static_cast<const void*>(*value) << " at index: " << index
|
||||
<< std::endl;
|
||||
|
||||
detail::result_meta_data_t& meta_data = _handle->result_param_meta_data[index];
|
||||
meta_data.index = index;
|
||||
meta_data.len = len;
|
||||
meta_data.is_null = nullptr;
|
||||
meta_data.text_buffer = value;
|
||||
if (meta_data.bound_text_buffer.empty())
|
||||
meta_data.bound_text_buffer.resize(8);
|
||||
|
||||
MYSQL_BIND& param = _handle->result_params[index];
|
||||
param.buffer_type = MYSQL_TYPE_STRING;
|
||||
param.buffer = meta_data.bound_text_buffer.data();
|
||||
param.buffer_length = meta_data.bound_text_buffer.size();
|
||||
param.length = &meta_data.bound_len;
|
||||
param.is_null = &meta_data.bound_is_null;
|
||||
param.is_unsigned = false;
|
||||
param.error = &meta_data.bound_error;
|
||||
}
|
||||
void bind_result_t::_bind_blob_result(size_t index, const char** value, size_t* len)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: binding text result " << static_cast<const void*>(*value) << " at index: " << index
|
||||
<< std::endl;
|
||||
|
||||
detail::result_meta_data_t& meta_data = _handle->result_param_meta_data[index];
|
||||
meta_data.index = index;
|
||||
meta_data.len = len;
|
||||
meta_data.is_null = nullptr;
|
||||
meta_data.text_buffer = value;
|
||||
if (meta_data.bound_text_buffer.empty())
|
||||
meta_data.bound_text_buffer.resize(8);
|
||||
|
||||
MYSQL_BIND& param = _handle->result_params[index];
|
||||
param.buffer_type = MYSQL_TYPE_BLOB;
|
||||
param.buffer = meta_data.bound_text_buffer.data();
|
||||
param.buffer_length = meta_data.bound_text_buffer.size();
|
||||
param.length = &meta_data.bound_len;
|
||||
param.is_null = &meta_data.bound_is_null;
|
||||
param.is_unsigned = false;
|
||||
param.error = &meta_data.bound_error;
|
||||
}
|
||||
|
||||
void bind_result_t::_bind_date_result(size_t index, ::sqlpp::chrono::day_point* value, bool* is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: binding date result " << static_cast<void*>(value) << " at index: " << index
|
||||
<< std::endl;
|
||||
|
||||
detail::result_meta_data_t& meta_data = _handle->result_param_meta_data[index];
|
||||
meta_data.index = index;
|
||||
meta_data.len = nullptr;
|
||||
meta_data.is_null = is_null;
|
||||
meta_data.text_buffer = nullptr;
|
||||
meta_data.bound_text_buffer.resize(sizeof(MYSQL_TIME));
|
||||
|
||||
MYSQL_BIND& param = _handle->result_params[index];
|
||||
param.buffer_type = MYSQL_TYPE_DATE;
|
||||
param.buffer = meta_data.bound_text_buffer.data();
|
||||
param.buffer_length = meta_data.bound_text_buffer.size();
|
||||
param.length = &meta_data.bound_len;
|
||||
param.is_null = &meta_data.bound_is_null;
|
||||
param.is_unsigned = false;
|
||||
param.error = &meta_data.bound_error;
|
||||
}
|
||||
|
||||
void bind_result_t::_bind_date_time_result(size_t index, ::sqlpp::chrono::microsecond_point* value, bool* is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: binding date time result " << static_cast<void*>(value) << " at index: " << index
|
||||
<< std::endl;
|
||||
|
||||
detail::result_meta_data_t& meta_data = _handle->result_param_meta_data[index];
|
||||
meta_data.index = index;
|
||||
meta_data.len = nullptr;
|
||||
meta_data.is_null = is_null;
|
||||
meta_data.text_buffer = nullptr;
|
||||
meta_data.bound_text_buffer.resize(sizeof(MYSQL_TIME));
|
||||
|
||||
MYSQL_BIND& param = _handle->result_params[index];
|
||||
param.buffer_type = MYSQL_TYPE_DATETIME;
|
||||
param.buffer = meta_data.bound_text_buffer.data();
|
||||
param.buffer_length = meta_data.bound_text_buffer.size();
|
||||
param.length = &meta_data.bound_len;
|
||||
param.is_null = &meta_data.bound_is_null;
|
||||
param.is_unsigned = false;
|
||||
param.error = &meta_data.bound_error;
|
||||
}
|
||||
|
||||
void bind_result_t::_post_bind_date_result(size_t index, ::sqlpp::chrono::day_point* value, bool* is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: post binding date result " << static_cast<void*>(value) << " at index: " << index
|
||||
<< std::endl;
|
||||
|
||||
if (not *is_null)
|
||||
{
|
||||
const auto& dt =
|
||||
*reinterpret_cast<const MYSQL_TIME*>(_handle->result_param_meta_data[index].bound_text_buffer.data());
|
||||
*is_null = false;
|
||||
*value = ::date::year(dt.year) / ::date::month(dt.month) / ::date::day(dt.day);
|
||||
}
|
||||
}
|
||||
|
||||
void bind_result_t::_post_bind_date_time_result(size_t index,
|
||||
::sqlpp::chrono::microsecond_point* value,
|
||||
bool* is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: binding date time result " << static_cast<void*>(value) << " at index: " << index
|
||||
<< std::endl;
|
||||
|
||||
if (not *is_null)
|
||||
{
|
||||
const auto& dt =
|
||||
*reinterpret_cast<const MYSQL_TIME*>(_handle->result_param_meta_data[index].bound_text_buffer.data());
|
||||
*is_null = false;
|
||||
*value = ::sqlpp::chrono::day_point(::date::year(dt.year) / ::date::month(dt.month) / ::date::day(dt.day)) +
|
||||
std::chrono::hours(dt.hour) + std::chrono::minutes(dt.minute) + std::chrono::seconds(dt.second) +
|
||||
std::chrono::microseconds(dt.second_part);
|
||||
}
|
||||
}
|
||||
|
||||
void bind_result_t::bind_impl()
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: Binding results for handle at " << _handle.get() << std::endl;
|
||||
|
||||
if (mysql_stmt_bind_result(_handle->mysql_stmt, _handle->result_params.data()))
|
||||
{
|
||||
throw sqlpp::exception(std::string("MySQL: mysql_stmt_bind_result: ") + mysql_stmt_error(_handle->mysql_stmt));
|
||||
}
|
||||
}
|
||||
|
||||
bool bind_result_t::next_impl()
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: Accessing next row of handle at " << _handle.get() << std::endl;
|
||||
|
||||
auto flag = mysql_stmt_fetch(_handle->mysql_stmt);
|
||||
|
||||
switch (flag)
|
||||
{
|
||||
case 0:
|
||||
case MYSQL_DATA_TRUNCATED:
|
||||
{
|
||||
bool need_to_rebind = false;
|
||||
for (auto& r : _handle->result_param_meta_data)
|
||||
{
|
||||
if (r.len)
|
||||
{
|
||||
if (r.bound_is_null)
|
||||
{
|
||||
*r.text_buffer = nullptr;
|
||||
*r.len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (r.bound_len > r.bound_text_buffer.size())
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: Need to reallocate buffer " << static_cast<const void*>(*r.text_buffer)
|
||||
<< " at index " << r.index << " for handle at " << _handle.get() << std::endl;
|
||||
need_to_rebind = true;
|
||||
r.bound_text_buffer.resize(r.bound_len);
|
||||
MYSQL_BIND& param = _handle->result_params[r.index];
|
||||
param.buffer = r.bound_text_buffer.data();
|
||||
param.buffer_length = r.bound_text_buffer.size();
|
||||
|
||||
auto err =
|
||||
mysql_stmt_fetch_column(_handle->mysql_stmt, ¶m, r.index, 0);
|
||||
if (err)
|
||||
throw sqlpp::exception(std::string("MySQL: Fetch column after reallocate failed: ") +
|
||||
"error-code: " + std::to_string(err) + ", stmt-error: " +
|
||||
mysql_stmt_error(_handle->mysql_stmt) + ", stmt-errno: " +
|
||||
std::to_string(mysql_stmt_errno(_handle->mysql_stmt)));
|
||||
}
|
||||
*r.text_buffer = r.bound_text_buffer.data();
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: New buffer " << static_cast<const void*>(*r.text_buffer) << " at index "
|
||||
<< r.index << " for handle at " << _handle.get() << std::endl;
|
||||
|
||||
*r.len = r.bound_len;
|
||||
}
|
||||
}
|
||||
if (r.is_null)
|
||||
*r.is_null = r.bound_is_null;
|
||||
}
|
||||
if (need_to_rebind)
|
||||
bind_impl();
|
||||
}
|
||||
return true;
|
||||
case 1:
|
||||
throw sqlpp::exception(std::string("MySQL: Could not fetch next result: ") +
|
||||
mysql_stmt_error(_handle->mysql_stmt));
|
||||
case MYSQL_NO_DATA:
|
||||
return false;
|
||||
default:
|
||||
throw sqlpp::exception("MySQL: Unexpected return value for mysql_stmt_fetch()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
184
src/mysql/char_result.cpp
Normal file
184
src/mysql/char_result.cpp
Normal file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "detail/result_handle.h"
|
||||
#include <cctype>
|
||||
#include <ciso646>
|
||||
#include <date/date.h>
|
||||
#include <iostream>
|
||||
#include <sqlpp11/mysql/char_result.h>
|
||||
#include <vector>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
char_result_t::char_result_t()
|
||||
{
|
||||
}
|
||||
|
||||
char_result_t::char_result_t(std::unique_ptr<detail::result_handle>&& handle) : _handle(std::move(handle))
|
||||
{
|
||||
if (_invalid())
|
||||
throw sqlpp::exception("MySQL: Constructing char_result without valid handle");
|
||||
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: Constructing result, using handle at " << _handle.get() << std::endl;
|
||||
}
|
||||
|
||||
char_result_t::~char_result_t() = default;
|
||||
char_result_t::char_result_t(char_result_t&& rhs) = default;
|
||||
char_result_t& char_result_t::operator=(char_result_t&&) = default;
|
||||
|
||||
namespace
|
||||
{
|
||||
const auto date_digits = std::vector<char>{1, 1, 1, 1, 0, 1, 1, 0, 1, 1}; // 2015-10-28
|
||||
const auto time_digits = std::vector<char>{0, 1, 1, 0, 1, 1, 0, 1, 1}; // T23:00:12
|
||||
|
||||
auto check_digits(const char* text, const std::vector<char>& digitFlags) -> bool
|
||||
{
|
||||
for (const auto digitFlag : digitFlags)
|
||||
{
|
||||
if (digitFlag)
|
||||
{
|
||||
if (not std::isdigit(*text))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (std::isdigit(*text) or *text == '\0')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
++text;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool char_result_t::_invalid() const
|
||||
{
|
||||
return !_handle or !*_handle;
|
||||
}
|
||||
|
||||
void char_result_t::_bind_date_result(size_t index, ::sqlpp::chrono::day_point* value, bool* is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: parsing date result at index: " << index << std::endl;
|
||||
|
||||
*is_null = (_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr);
|
||||
if (*is_null)
|
||||
{
|
||||
*value = {};
|
||||
return;
|
||||
}
|
||||
|
||||
const auto date_string = _char_result_row.data[index];
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: date string: " << date_string << std::endl;
|
||||
|
||||
if (check_digits(date_string, date_digits))
|
||||
{
|
||||
const auto ymd = ::date::year(std::atoi(date_string)) / atoi(date_string + 5) / atoi(date_string + 8);
|
||||
*value = ::sqlpp::chrono::day_point(ymd);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: invalid date result: " << date_string << std::endl;
|
||||
*value = {};
|
||||
}
|
||||
}
|
||||
|
||||
void char_result_t::_bind_date_time_result(size_t index, ::sqlpp::chrono::microsecond_point* value, bool* is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: parsing date result at index: " << index << std::endl;
|
||||
|
||||
*is_null = (_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr);
|
||||
if (*is_null)
|
||||
{
|
||||
*value = {};
|
||||
return;
|
||||
}
|
||||
|
||||
const auto date_time_string = _char_result_row.data[index];
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: date_time string: " << date_time_string << std::endl;
|
||||
|
||||
if (check_digits(date_time_string, date_digits))
|
||||
{
|
||||
const auto ymd =
|
||||
::date::year(std::atoi(date_time_string)) / atoi(date_time_string + 5) / atoi(date_time_string + 8);
|
||||
*value = ::sqlpp::chrono::day_point(ymd);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: invalid date_time result: " << date_time_string << std::endl;
|
||||
*value = {};
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const auto time_string = date_time_string + 10;
|
||||
if (check_digits(time_string, time_digits))
|
||||
{
|
||||
*value += ::std::chrono::hours(std::atoi(time_string + 1)) + std::chrono::minutes(std::atoi(time_string + 4)) +
|
||||
std::chrono::seconds(std::atoi(time_string + 7));
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto mu_string = time_string + 9;
|
||||
if (mu_string[0] == '\0')
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto factor = 100 * 1000;
|
||||
for (auto i = 1u; i <= 6u and std::isdigit(mu_string[i]); ++i, factor /= 10)
|
||||
{
|
||||
*value += ::std::chrono::microseconds(factor * (mu_string[i] - '0'));
|
||||
}
|
||||
}
|
||||
|
||||
bool char_result_t::next_impl()
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: Accessing next row of handle at " << _handle.get() << std::endl;
|
||||
|
||||
_char_result_row.data = const_cast<const char**>(mysql_fetch_row(_handle->mysql_res));
|
||||
_char_result_row.len = mysql_fetch_lengths(_handle->mysql_res);
|
||||
|
||||
return _char_result_row.data;
|
||||
}
|
||||
}
|
||||
}
|
288
src/mysql/connection.cpp
Normal file
288
src/mysql/connection.cpp
Normal file
@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <ciso646>
|
||||
#include <iostream>
|
||||
#include "detail/connection_handle.h"
|
||||
#include "detail/prepared_statement_handle.h"
|
||||
#include "detail/result_handle.h"
|
||||
#include <sqlpp11/exception.h>
|
||||
#include <sqlpp11/mysql/connection.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
scoped_library_initializer_t::scoped_library_initializer_t(int argc, char** argv, char** groups)
|
||||
{
|
||||
mysql_library_init(argc, argv, groups);
|
||||
}
|
||||
|
||||
scoped_library_initializer_t::~scoped_library_initializer_t()
|
||||
{
|
||||
mysql_library_end();
|
||||
}
|
||||
|
||||
void global_library_init(int argc, char** argv, char** groups)
|
||||
{
|
||||
static const auto global_init_and_end = scoped_library_initializer_t(argc, argv, groups);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct MySqlThreadInitializer
|
||||
{
|
||||
MySqlThreadInitializer()
|
||||
{
|
||||
if (!mysql_thread_safe())
|
||||
{
|
||||
throw sqlpp::exception("MySQL error: Operating on a non-threadsafe client");
|
||||
}
|
||||
mysql_thread_init();
|
||||
}
|
||||
|
||||
~MySqlThreadInitializer()
|
||||
{
|
||||
mysql_thread_end();
|
||||
}
|
||||
};
|
||||
|
||||
void thread_init()
|
||||
{
|
||||
thread_local MySqlThreadInitializer threadInitializer;
|
||||
}
|
||||
|
||||
void execute_statement(detail::connection_handle_t& handle, const std::string& statement)
|
||||
{
|
||||
thread_init();
|
||||
|
||||
if (handle.config->debug)
|
||||
std::cerr << "MySQL debug: Executing: '" << statement << "'" << std::endl;
|
||||
|
||||
if (mysql_query(handle.mysql.get(), statement.c_str()))
|
||||
{
|
||||
throw sqlpp::exception("MySQL error: Could not execute MySQL-statement: " +
|
||||
std::string(mysql_error(handle.mysql.get())) + " (statement was >>" + statement +
|
||||
"<<\n");
|
||||
}
|
||||
}
|
||||
|
||||
void execute_prepared_statement(detail::prepared_statement_handle_t& prepared_statement)
|
||||
{
|
||||
thread_init();
|
||||
|
||||
if (prepared_statement.debug)
|
||||
std::cerr << "MySQL debug: Executing prepared_statement" << std::endl;
|
||||
|
||||
if (mysql_stmt_bind_param(prepared_statement.mysql_stmt, prepared_statement.stmt_params.data()))
|
||||
{
|
||||
throw sqlpp::exception(std::string("MySQL error: Could not bind parameters to statement") +
|
||||
mysql_stmt_error(prepared_statement.mysql_stmt));
|
||||
}
|
||||
|
||||
if (mysql_stmt_execute(prepared_statement.mysql_stmt))
|
||||
{
|
||||
throw sqlpp::exception(std::string("MySQL error: Could not execute prepared statement: ") +
|
||||
mysql_stmt_error(prepared_statement.mysql_stmt));
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<detail::prepared_statement_handle_t> prepare_statement(detail::connection_handle_t& handle,
|
||||
const std::string& statement,
|
||||
size_t no_of_parameters,
|
||||
size_t no_of_columns)
|
||||
{
|
||||
thread_init();
|
||||
|
||||
if (handle.config->debug)
|
||||
std::cerr << "MySQL debug: Preparing: '" << statement << "'" << std::endl;
|
||||
|
||||
auto prepared_statement = std::make_shared<detail::prepared_statement_handle_t>(
|
||||
mysql_stmt_init(handle.mysql.get()), no_of_parameters, no_of_columns, handle.config->debug);
|
||||
if (not prepared_statement)
|
||||
{
|
||||
throw sqlpp::exception("MySQL error: Could not allocate prepared statement\n");
|
||||
}
|
||||
if (mysql_stmt_prepare(prepared_statement->mysql_stmt, statement.data(), statement.size()))
|
||||
{
|
||||
throw sqlpp::exception("MySQL error: Could not prepare statement: " +
|
||||
std::string(mysql_error(handle.mysql.get())) + " (statement was >>" + statement +
|
||||
"<<\n");
|
||||
}
|
||||
|
||||
return prepared_statement;
|
||||
}
|
||||
}
|
||||
|
||||
connection::connection(const std::shared_ptr<connection_config>& config)
|
||||
: _handle(new detail::connection_handle_t(config))
|
||||
{
|
||||
}
|
||||
|
||||
connection::~connection()
|
||||
{
|
||||
}
|
||||
|
||||
connection::connection(connection&& other)
|
||||
{
|
||||
this->_transaction_active = other._transaction_active;
|
||||
this->_handle = std::move(other._handle);
|
||||
}
|
||||
|
||||
bool connection::is_valid()
|
||||
{
|
||||
return _handle->is_valid();
|
||||
}
|
||||
void connection::reconnect()
|
||||
{
|
||||
return _handle->reconnect();
|
||||
}
|
||||
|
||||
const std::shared_ptr<connection_config> connection::get_config()
|
||||
{
|
||||
return _handle->config;
|
||||
}
|
||||
|
||||
char_result_t connection::select_impl(const std::string& statement)
|
||||
{
|
||||
execute_statement(*_handle, statement);
|
||||
std::unique_ptr<detail::result_handle> result_handle(
|
||||
new detail::result_handle(mysql_store_result(_handle->mysql.get()), _handle->config->debug));
|
||||
if (!*result_handle)
|
||||
{
|
||||
throw sqlpp::exception("MySQL error: Could not store result set: " +
|
||||
std::string(mysql_error(_handle->mysql.get())));
|
||||
}
|
||||
|
||||
return {std::move(result_handle)};
|
||||
}
|
||||
|
||||
bind_result_t connection::run_prepared_select_impl(prepared_statement_t& prepared_statement)
|
||||
{
|
||||
execute_prepared_statement(*prepared_statement._handle);
|
||||
return prepared_statement._handle;
|
||||
}
|
||||
|
||||
size_t connection::run_prepared_insert_impl(prepared_statement_t& prepared_statement)
|
||||
{
|
||||
execute_prepared_statement(*prepared_statement._handle);
|
||||
return mysql_stmt_insert_id(prepared_statement._handle->mysql_stmt);
|
||||
}
|
||||
|
||||
size_t connection::run_prepared_update_impl(prepared_statement_t& prepared_statement)
|
||||
{
|
||||
execute_prepared_statement(*prepared_statement._handle);
|
||||
return mysql_stmt_affected_rows(prepared_statement._handle->mysql_stmt);
|
||||
}
|
||||
|
||||
size_t connection::run_prepared_remove_impl(prepared_statement_t& prepared_statement)
|
||||
{
|
||||
execute_prepared_statement(*prepared_statement._handle);
|
||||
return mysql_stmt_affected_rows(prepared_statement._handle->mysql_stmt);
|
||||
}
|
||||
|
||||
prepared_statement_t connection::prepare_impl(const std::string& statement,
|
||||
size_t no_of_parameters,
|
||||
size_t no_of_columns)
|
||||
{
|
||||
return prepare_statement(*_handle, statement, no_of_parameters, no_of_columns);
|
||||
}
|
||||
|
||||
size_t connection::insert_impl(const std::string& statement)
|
||||
{
|
||||
execute_statement(*_handle, statement);
|
||||
|
||||
return mysql_insert_id(_handle->mysql.get());
|
||||
}
|
||||
|
||||
void connection::execute(const std::string& command)
|
||||
{
|
||||
execute_statement(*_handle, command);
|
||||
}
|
||||
|
||||
size_t connection::update_impl(const std::string& statement)
|
||||
{
|
||||
execute_statement(*_handle, statement);
|
||||
return mysql_affected_rows(_handle->mysql.get());
|
||||
}
|
||||
|
||||
size_t connection::remove_impl(const std::string& statement)
|
||||
{
|
||||
execute_statement(*_handle, statement);
|
||||
return mysql_affected_rows(_handle->mysql.get());
|
||||
}
|
||||
|
||||
std::string connection::escape(const std::string& s) const
|
||||
{
|
||||
std::unique_ptr<char[]> dest(new char[s.size() * 2 + 1]);
|
||||
mysql_real_escape_string(_handle->mysql.get(), dest.get(), s.c_str(), s.size());
|
||||
return dest.get();
|
||||
}
|
||||
|
||||
void connection::start_transaction()
|
||||
{
|
||||
if (_transaction_active)
|
||||
{
|
||||
throw sqlpp::exception("MySQL: Cannot have more than one open transaction per connection");
|
||||
}
|
||||
execute_statement(*_handle, "START TRANSACTION");
|
||||
_transaction_active = true;
|
||||
}
|
||||
|
||||
void connection::commit_transaction()
|
||||
{
|
||||
if (not _transaction_active)
|
||||
{
|
||||
throw sqlpp::exception("MySQL: Cannot commit a finished or failed transaction");
|
||||
}
|
||||
_transaction_active = false;
|
||||
execute_statement(*_handle, "COMMIT");
|
||||
}
|
||||
|
||||
void connection::rollback_transaction(bool report)
|
||||
{
|
||||
if (not _transaction_active)
|
||||
{
|
||||
throw sqlpp::exception("MySQL: Cannot rollback a finished or failed transaction");
|
||||
}
|
||||
if (report)
|
||||
{
|
||||
std::cerr << "MySQL warning: Rolling back unfinished transaction" << std::endl;
|
||||
}
|
||||
_transaction_active = false;
|
||||
execute_statement(*_handle, "ROLLBACK");
|
||||
}
|
||||
|
||||
void connection::report_rollback_failure(const std::string message) noexcept
|
||||
{
|
||||
std::cerr << "MySQL message:" << message << std::endl;
|
||||
}
|
||||
|
||||
MYSQL* connection::get_handle(){
|
||||
return _handle->mysql.get();
|
||||
}
|
||||
}
|
||||
}
|
293
src/mysql/connection.cpp.orig
Normal file
293
src/mysql/connection.cpp.orig
Normal file
@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <ciso646>
|
||||
#include <iostream>
|
||||
#include "detail/connection_handle.h"
|
||||
#include "detail/prepared_statement_handle.h"
|
||||
#include "detail/result_handle.h"
|
||||
#include <sqlpp11/exception.h>
|
||||
#include <sqlpp11/mysql/connection.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
scoped_library_initializer_t::scoped_library_initializer_t(int argc, char** argv, char** groups)
|
||||
{
|
||||
mysql_library_init(argc, argv, groups);
|
||||
}
|
||||
|
||||
scoped_library_initializer_t::~scoped_library_initializer_t()
|
||||
{
|
||||
mysql_library_end();
|
||||
}
|
||||
|
||||
void global_library_init(int argc, char** argv, char** groups)
|
||||
{
|
||||
static const auto global_init_and_end = scoped_library_initializer_t(argc, argv, groups);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct MySqlThreadInitializer
|
||||
{
|
||||
MySqlThreadInitializer()
|
||||
{
|
||||
if (!mysql_thread_safe())
|
||||
{
|
||||
throw sqlpp::exception("MySQL error: Operating on a non-threadsafe client");
|
||||
}
|
||||
mysql_thread_init();
|
||||
}
|
||||
|
||||
~MySqlThreadInitializer()
|
||||
{
|
||||
mysql_thread_end();
|
||||
}
|
||||
};
|
||||
|
||||
void thread_init()
|
||||
{
|
||||
thread_local MySqlThreadInitializer threadInitializer;
|
||||
}
|
||||
|
||||
void execute_statement(detail::connection_handle_t& handle, const std::string& statement)
|
||||
{
|
||||
thread_init();
|
||||
|
||||
if (handle.config->debug)
|
||||
std::cerr << "MySQL debug: Executing: '" << statement << "'" << std::endl;
|
||||
|
||||
if (mysql_query(handle.mysql.get(), statement.c_str()))
|
||||
{
|
||||
throw sqlpp::exception("MySQL error: Could not execute MySQL-statement: " +
|
||||
std::string(mysql_error(handle.mysql.get())) + " (statement was >>" + statement +
|
||||
"<<\n");
|
||||
}
|
||||
}
|
||||
|
||||
void execute_prepared_statement(detail::prepared_statement_handle_t& prepared_statement)
|
||||
{
|
||||
thread_init();
|
||||
|
||||
if (prepared_statement.debug)
|
||||
std::cerr << "MySQL debug: Executing prepared_statement" << std::endl;
|
||||
|
||||
if (mysql_stmt_bind_param(prepared_statement.mysql_stmt, prepared_statement.stmt_params.data()))
|
||||
{
|
||||
throw sqlpp::exception(std::string("MySQL error: Could not bind parameters to statement") +
|
||||
mysql_stmt_error(prepared_statement.mysql_stmt));
|
||||
}
|
||||
|
||||
if (mysql_stmt_execute(prepared_statement.mysql_stmt))
|
||||
{
|
||||
throw sqlpp::exception(std::string("MySQL error: Could not execute prepared statement: ") +
|
||||
mysql_stmt_error(prepared_statement.mysql_stmt));
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<detail::prepared_statement_handle_t> prepare_statement(detail::connection_handle_t& handle,
|
||||
const std::string& statement,
|
||||
size_t no_of_parameters,
|
||||
size_t no_of_columns)
|
||||
{
|
||||
thread_init();
|
||||
|
||||
if (handle.config->debug)
|
||||
std::cerr << "MySQL debug: Preparing: '" << statement << "'" << std::endl;
|
||||
|
||||
auto prepared_statement = std::make_shared<detail::prepared_statement_handle_t>(
|
||||
mysql_stmt_init(handle.mysql.get()), no_of_parameters, no_of_columns, handle.config->debug);
|
||||
if (not prepared_statement)
|
||||
{
|
||||
throw sqlpp::exception("MySQL error: Could not allocate prepared statement\n");
|
||||
}
|
||||
if (mysql_stmt_prepare(prepared_statement->mysql_stmt, statement.data(), statement.size()))
|
||||
{
|
||||
throw sqlpp::exception("MySQL error: Could not prepare statement: " +
|
||||
std::string(mysql_error(handle.mysql.get())) + " (statement was >>" + statement +
|
||||
"<<\n");
|
||||
}
|
||||
|
||||
return prepared_statement;
|
||||
}
|
||||
}
|
||||
|
||||
connection::connection(const std::shared_ptr<connection_config>& config)
|
||||
: _handle(new detail::connection_handle_t(config))
|
||||
{
|
||||
}
|
||||
|
||||
connection::~connection()
|
||||
{
|
||||
}
|
||||
|
||||
connection::connection(connection&& other)
|
||||
{
|
||||
this->_transaction_active = other._transaction_active;
|
||||
this->_handle = std::move(other._handle);
|
||||
}
|
||||
|
||||
bool connection::is_valid()
|
||||
{
|
||||
return _handle->is_valid();
|
||||
}
|
||||
void connection::reconnect()
|
||||
{
|
||||
return _handle->reconnect();
|
||||
}
|
||||
|
||||
const std::shared_ptr<connection_config> connection::get_config()
|
||||
{
|
||||
return _handle->config;
|
||||
}
|
||||
|
||||
char_result_t connection::select_impl(const std::string& statement)
|
||||
{
|
||||
execute_statement(*_handle, statement);
|
||||
std::unique_ptr<detail::result_handle> result_handle(
|
||||
new detail::result_handle(mysql_store_result(_handle->mysql.get()), _handle->config->debug));
|
||||
if (!*result_handle)
|
||||
{
|
||||
throw sqlpp::exception("MySQL error: Could not store result set: " +
|
||||
std::string(mysql_error(_handle->mysql.get())));
|
||||
}
|
||||
|
||||
return {std::move(result_handle)};
|
||||
}
|
||||
|
||||
bind_result_t connection::run_prepared_select_impl(prepared_statement_t& prepared_statement)
|
||||
{
|
||||
execute_prepared_statement(*prepared_statement._handle);
|
||||
return prepared_statement._handle;
|
||||
}
|
||||
|
||||
size_t connection::run_prepared_insert_impl(prepared_statement_t& prepared_statement)
|
||||
{
|
||||
execute_prepared_statement(*prepared_statement._handle);
|
||||
return mysql_stmt_insert_id(prepared_statement._handle->mysql_stmt);
|
||||
}
|
||||
|
||||
size_t connection::run_prepared_update_impl(prepared_statement_t& prepared_statement)
|
||||
{
|
||||
execute_prepared_statement(*prepared_statement._handle);
|
||||
return mysql_stmt_affected_rows(prepared_statement._handle->mysql_stmt);
|
||||
}
|
||||
|
||||
size_t connection::run_prepared_remove_impl(prepared_statement_t& prepared_statement)
|
||||
{
|
||||
execute_prepared_statement(*prepared_statement._handle);
|
||||
return mysql_stmt_affected_rows(prepared_statement._handle->mysql_stmt);
|
||||
}
|
||||
|
||||
prepared_statement_t connection::prepare_impl(const std::string& statement,
|
||||
size_t no_of_parameters,
|
||||
size_t no_of_columns)
|
||||
{
|
||||
return prepare_statement(*_handle, statement, no_of_parameters, no_of_columns);
|
||||
}
|
||||
|
||||
size_t connection::insert_impl(const std::string& statement)
|
||||
{
|
||||
execute_statement(*_handle, statement);
|
||||
|
||||
return mysql_insert_id(_handle->mysql.get());
|
||||
}
|
||||
|
||||
void connection::execute(const std::string& command)
|
||||
{
|
||||
execute_statement(*_handle, command);
|
||||
}
|
||||
|
||||
size_t connection::update_impl(const std::string& statement)
|
||||
{
|
||||
execute_statement(*_handle, statement);
|
||||
return mysql_affected_rows(_handle->mysql.get());
|
||||
}
|
||||
|
||||
size_t connection::remove_impl(const std::string& statement)
|
||||
{
|
||||
execute_statement(*_handle, statement);
|
||||
return mysql_affected_rows(_handle->mysql.get());
|
||||
}
|
||||
|
||||
std::string connection::escape(const std::string& s) const
|
||||
{
|
||||
std::unique_ptr<char[]> dest(new char[s.size() * 2 + 1]);
|
||||
mysql_real_escape_string(_handle->mysql.get(), dest.get(), s.c_str(), s.size());
|
||||
return dest.get();
|
||||
}
|
||||
|
||||
void connection::start_transaction()
|
||||
{
|
||||
if (_transaction_active)
|
||||
{
|
||||
throw sqlpp::exception("MySQL: Cannot have more than one open transaction per connection");
|
||||
}
|
||||
execute_statement(*_handle, "START TRANSACTION");
|
||||
_transaction_active = true;
|
||||
}
|
||||
|
||||
void connection::commit_transaction()
|
||||
{
|
||||
if (not _transaction_active)
|
||||
{
|
||||
throw sqlpp::exception("MySQL: Cannot commit a finished or failed transaction");
|
||||
}
|
||||
_transaction_active = false;
|
||||
execute_statement(*_handle, "COMMIT");
|
||||
}
|
||||
|
||||
void connection::rollback_transaction(bool report)
|
||||
{
|
||||
if (not _transaction_active)
|
||||
{
|
||||
throw sqlpp::exception("MySQL: Cannot rollback a finished or failed transaction");
|
||||
}
|
||||
if (report)
|
||||
{
|
||||
std::cerr << "MySQL warning: Rolling back unfinished transaction" << std::endl;
|
||||
}
|
||||
_transaction_active = false;
|
||||
execute_statement(*_handle, "ROLLBACK");
|
||||
}
|
||||
|
||||
void connection::report_rollback_failure(const std::string message) noexcept
|
||||
{
|
||||
std::cerr << "MySQL message:" << message << std::endl;
|
||||
}
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
MYSQL* connection::get_handle(){
|
||||
=======
|
||||
MYSQL* connection::get_handle()
|
||||
{
|
||||
>>>>>>> Stashed changes
|
||||
return _handle->mysql.get();
|
||||
}
|
||||
}
|
||||
}
|
99
src/mysql/detail/connection_handle.cpp
Normal file
99
src/mysql/detail/connection_handle.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "connection_handle.h"
|
||||
#include <ciso646>
|
||||
#include <sqlpp11/exception.h>
|
||||
#include <sqlpp11/mysql/connection_config.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
void connect(MYSQL* mysql, const connection_config& config)
|
||||
{
|
||||
if (!mysql_real_connect(mysql, config.host.empty() ? nullptr : config.host.c_str(),
|
||||
config.user.empty() ? nullptr : config.user.c_str(),
|
||||
config.password.empty() ? nullptr : config.password.c_str(), nullptr, config.port,
|
||||
config.unix_socket.empty() ? nullptr : config.unix_socket.c_str(), config.client_flag))
|
||||
{
|
||||
throw sqlpp::exception("MySQL: could not connect to server: " + std::string(mysql_error(mysql)));
|
||||
}
|
||||
|
||||
if (mysql_set_character_set(mysql, config.charset.c_str()))
|
||||
{
|
||||
throw sqlpp::exception("MySQL error: can't set character set " + config.charset);
|
||||
}
|
||||
|
||||
if (not config.database.empty() and mysql_select_db(mysql, config.database.c_str()))
|
||||
{
|
||||
throw sqlpp::exception("MySQL error: can't select database '" + config.database + "'");
|
||||
}
|
||||
}
|
||||
|
||||
void handle_cleanup(MYSQL* mysql)
|
||||
{
|
||||
mysql_close(mysql);
|
||||
}
|
||||
|
||||
connection_handle_t::connection_handle_t(const std::shared_ptr<connection_config>& conf)
|
||||
: config(conf), mysql(mysql_init(nullptr), handle_cleanup)
|
||||
{
|
||||
if (not mysql)
|
||||
{
|
||||
throw sqlpp::exception("MySQL: could not init mysql data structure");
|
||||
}
|
||||
|
||||
if (config->auto_reconnect)
|
||||
{
|
||||
my_bool my_true = true;
|
||||
if (mysql_options(mysql.get(), MYSQL_OPT_RECONNECT, &my_true))
|
||||
{
|
||||
throw sqlpp::exception("MySQL: could not set option MYSQL_OPT_RECONNECT");
|
||||
}
|
||||
}
|
||||
|
||||
connect(mysql.get(), *config);
|
||||
}
|
||||
|
||||
connection_handle_t::~connection_handle_t()
|
||||
{
|
||||
}
|
||||
|
||||
bool connection_handle_t::is_valid()
|
||||
{
|
||||
return mysql_ping(mysql.get()) == 0;
|
||||
}
|
||||
|
||||
void connection_handle_t::reconnect()
|
||||
{
|
||||
connect(mysql.get(), *config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
62
src/mysql/detail/connection_handle.h
Normal file
62
src/mysql/detail/connection_handle.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SQLPP_MYSQL_CONNECTION_HANDLE_H
|
||||
#define SQLPP_MYSQL_CONNECTION_HANDLE_H
|
||||
|
||||
#include <memory>
|
||||
#include "../sqlpp_mysql.h"
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
struct connection_config;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
void handle_cleanup(MYSQL* mysql);
|
||||
|
||||
struct connection_handle_t
|
||||
{
|
||||
const std::shared_ptr<connection_config> config;
|
||||
std::unique_ptr<MYSQL, void (*)(MYSQL*)> mysql;
|
||||
|
||||
connection_handle_t(const std::shared_ptr<connection_config>& config);
|
||||
~connection_handle_t();
|
||||
connection_handle_t(const connection_handle_t&) = delete;
|
||||
connection_handle_t(connection_handle_t&&) = delete;
|
||||
connection_handle_t& operator=(const connection_handle_t&) = delete;
|
||||
connection_handle_t& operator=(connection_handle_t&&) = delete;
|
||||
|
||||
bool is_valid();
|
||||
void reconnect();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
109
src/mysql/detail/prepared_statement_handle.h
Normal file
109
src/mysql/detail/prepared_statement_handle.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SQLPP_MYSQL_DETAIL_PREPARED_STATEMENT_HANDLE_H
|
||||
#define SQLPP_MYSQL_DETAIL_PREPARED_STATEMENT_HANDLE_H
|
||||
|
||||
#include "../sqlpp_mysql.h"
|
||||
#include <vector>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct result_meta_data_t
|
||||
{
|
||||
size_t index;
|
||||
unsigned long bound_len;
|
||||
my_bool bound_is_null;
|
||||
my_bool bound_error;
|
||||
std::vector<char> bound_text_buffer; // also for blobs
|
||||
const char** text_buffer;
|
||||
size_t* len;
|
||||
bool* is_null;
|
||||
};
|
||||
|
||||
struct prepared_statement_handle_t
|
||||
{
|
||||
struct wrapped_bool
|
||||
{
|
||||
my_bool value;
|
||||
|
||||
wrapped_bool() : value(false)
|
||||
{
|
||||
}
|
||||
wrapped_bool(bool v) : value(v)
|
||||
{
|
||||
}
|
||||
wrapped_bool(const wrapped_bool&) = default;
|
||||
wrapped_bool(wrapped_bool&&) = default;
|
||||
wrapped_bool& operator=(const wrapped_bool&) = default;
|
||||
wrapped_bool& operator=(wrapped_bool&&) = default;
|
||||
~wrapped_bool() = default;
|
||||
};
|
||||
|
||||
MYSQL_STMT* mysql_stmt;
|
||||
std::vector<MYSQL_BIND> stmt_params;
|
||||
std::vector<MYSQL_TIME> stmt_date_time_param_buffer;
|
||||
std::vector<wrapped_bool> stmt_param_is_null; // my_bool is bool after 8.0, and vector<bool> is bad
|
||||
std::vector<MYSQL_BIND> result_params;
|
||||
std::vector<result_meta_data_t> result_param_meta_data;
|
||||
bool debug;
|
||||
|
||||
prepared_statement_handle_t(MYSQL_STMT* stmt, size_t no_of_parameters, size_t no_of_columns, bool debug_)
|
||||
: mysql_stmt(stmt),
|
||||
stmt_params(no_of_parameters, MYSQL_BIND{}),
|
||||
stmt_date_time_param_buffer(no_of_parameters, MYSQL_TIME{}),
|
||||
stmt_param_is_null(no_of_parameters, false),
|
||||
result_params(no_of_columns, MYSQL_BIND{}),
|
||||
result_param_meta_data(no_of_columns, result_meta_data_t{}),
|
||||
debug(debug_)
|
||||
{
|
||||
}
|
||||
|
||||
prepared_statement_handle_t(const prepared_statement_handle_t&) = delete;
|
||||
prepared_statement_handle_t(prepared_statement_handle_t&&) = default;
|
||||
prepared_statement_handle_t& operator=(const prepared_statement_handle_t&) = delete;
|
||||
prepared_statement_handle_t& operator=(prepared_statement_handle_t&&) = default;
|
||||
|
||||
~prepared_statement_handle_t()
|
||||
{
|
||||
if (mysql_stmt)
|
||||
mysql_stmt_close(mysql_stmt);
|
||||
}
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return !mysql_stmt;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
67
src/mysql/detail/result_handle.h
Normal file
67
src/mysql/detail/result_handle.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SQLPP_MYSQL_DETAIL_RESULT_HANDLE_H
|
||||
#define SQLPP_MYSQL_DETAIL_RESULT_HANDLE_H
|
||||
|
||||
#include "../sqlpp_mysql.h"
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct result_handle
|
||||
{
|
||||
MYSQL_RES* mysql_res;
|
||||
bool debug;
|
||||
|
||||
result_handle(MYSQL_RES* res, bool debug_) : mysql_res(res), debug(debug_)
|
||||
{
|
||||
}
|
||||
|
||||
result_handle(const result_handle&) = delete;
|
||||
result_handle(result_handle&&) = default;
|
||||
result_handle& operator=(const result_handle&) = delete;
|
||||
result_handle& operator=(result_handle&&) = default;
|
||||
|
||||
~result_handle()
|
||||
{
|
||||
if (mysql_res)
|
||||
mysql_free_result(mysql_res);
|
||||
}
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return !mysql_res;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
204
src/mysql/prepared_statement.cpp
Normal file
204
src/mysql/prepared_statement.cpp
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2016, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
// It seems that Windows.h will be included directly and indirectly.
|
||||
// These defines prevent min/max macros and a bunch of other stuff
|
||||
// to be defined in that header.
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#include "detail/prepared_statement_handle.h"
|
||||
#include <ciso646>
|
||||
#include <date/date.h>
|
||||
#include <iostream>
|
||||
#include <sqlpp11/mysql/prepared_statement.h>
|
||||
#include <string>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
prepared_statement_t::prepared_statement_t(std::shared_ptr<detail::prepared_statement_handle_t>&& handle)
|
||||
: _handle(std::move(handle))
|
||||
{
|
||||
if (_handle and _handle->debug)
|
||||
std::cerr << "MySQL debug: Constructing prepared_statement, using handle at " << _handle.get() << std::endl;
|
||||
}
|
||||
|
||||
void prepared_statement_t::_bind_boolean_parameter(size_t index, const signed char* value, bool is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: binding boolean parameter " << (*value ? "true" : "false") << " at index: " << index
|
||||
<< ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||
_handle->stmt_param_is_null[index] = is_null;
|
||||
MYSQL_BIND& param = _handle->stmt_params[index];
|
||||
param.buffer_type = MYSQL_TYPE_TINY;
|
||||
param.buffer = const_cast<signed char*>(value);
|
||||
param.buffer_length = sizeof(*value);
|
||||
param.length = ¶m.buffer_length;
|
||||
param.is_null = &_handle->stmt_param_is_null[index].value;
|
||||
param.is_unsigned = false;
|
||||
param.error = nullptr;
|
||||
}
|
||||
|
||||
void prepared_statement_t::_bind_integral_parameter(size_t index, const int64_t* value, bool is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: binding integral parameter " << *value << " at index: " << index << ", being "
|
||||
<< (is_null ? "" : "not ") << "null" << std::endl;
|
||||
_handle->stmt_param_is_null[index] = is_null;
|
||||
MYSQL_BIND& param = _handle->stmt_params[index];
|
||||
param.buffer_type = MYSQL_TYPE_LONGLONG;
|
||||
param.buffer = const_cast<int64_t*>(value);
|
||||
param.buffer_length = sizeof(*value);
|
||||
param.length = ¶m.buffer_length;
|
||||
param.is_null = &_handle->stmt_param_is_null[index].value;
|
||||
param.is_unsigned = false;
|
||||
param.error = nullptr;
|
||||
}
|
||||
|
||||
void prepared_statement_t::_bind_unsigned_integral_parameter(size_t index, const uint64_t* value, bool is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: binding unsigned integral parameter " << *value << " at index: " << index
|
||||
<< ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||
_handle->stmt_param_is_null[index] = is_null;
|
||||
MYSQL_BIND& param = _handle->stmt_params[index];
|
||||
param.buffer_type = MYSQL_TYPE_LONGLONG;
|
||||
param.buffer = const_cast<uint64_t*>(value);
|
||||
param.buffer_length = sizeof(*value);
|
||||
param.length = ¶m.buffer_length;
|
||||
param.is_null = &_handle->stmt_param_is_null[index].value;
|
||||
param.is_unsigned = true;
|
||||
param.error = nullptr;
|
||||
}
|
||||
|
||||
void prepared_statement_t::_bind_floating_point_parameter(size_t index, const double* value, bool is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: binding floating_point parameter " << *value << " at index: " << index << ", being "
|
||||
<< (is_null ? "" : "not ") << "null" << std::endl;
|
||||
_handle->stmt_param_is_null[index] = is_null;
|
||||
MYSQL_BIND& param = _handle->stmt_params[index];
|
||||
param.buffer_type = MYSQL_TYPE_DOUBLE;
|
||||
param.buffer = const_cast<double*>(value);
|
||||
param.buffer_length = sizeof(*value);
|
||||
param.length = ¶m.buffer_length;
|
||||
param.is_null = &_handle->stmt_param_is_null[index].value;
|
||||
param.is_unsigned = false;
|
||||
param.error = nullptr;
|
||||
}
|
||||
|
||||
void prepared_statement_t::_bind_text_parameter(size_t index, const std::string* value, bool is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: binding text parameter " << *value << " at index: " << index << ", being "
|
||||
<< (is_null ? "" : "not ") << "null" << std::endl;
|
||||
_handle->stmt_param_is_null[index] = is_null;
|
||||
MYSQL_BIND& param = _handle->stmt_params[index];
|
||||
param.buffer_type = MYSQL_TYPE_STRING;
|
||||
param.buffer = const_cast<char*>(value->data());
|
||||
param.buffer_length = value->size();
|
||||
param.length = ¶m.buffer_length;
|
||||
param.is_null = &_handle->stmt_param_is_null[index].value;
|
||||
param.is_unsigned = false;
|
||||
param.error = nullptr;
|
||||
}
|
||||
|
||||
void prepared_statement_t::_bind_date_parameter(size_t index, const ::sqlpp::chrono::day_point* value, bool is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: binding date parameter "
|
||||
<< " at index: " << index << ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||
|
||||
auto& bound_time = _handle->stmt_date_time_param_buffer[index];
|
||||
if (not is_null)
|
||||
{
|
||||
const auto ymd = ::date::year_month_day{*value};
|
||||
bound_time.year = static_cast<int>(ymd.year());
|
||||
bound_time.month = static_cast<unsigned>(ymd.month());
|
||||
bound_time.day = static_cast<unsigned>(ymd.day());
|
||||
if (_handle->debug)
|
||||
std::cerr << "bound values: " << bound_time.year << '-' << bound_time.month << '-' << bound_time.day << 'T'
|
||||
<< bound_time.hour << ':' << bound_time.minute << ':' << bound_time.second << std::endl;
|
||||
}
|
||||
|
||||
_handle->stmt_param_is_null[index] = is_null;
|
||||
MYSQL_BIND& param = _handle->stmt_params[index];
|
||||
param.buffer_type = MYSQL_TYPE_DATE;
|
||||
param.buffer = &bound_time;
|
||||
param.buffer_length = sizeof(MYSQL_TIME);
|
||||
param.length = ¶m.buffer_length;
|
||||
param.is_null = &_handle->stmt_param_is_null[index].value;
|
||||
param.is_unsigned = false;
|
||||
param.error = nullptr;
|
||||
}
|
||||
|
||||
void prepared_statement_t::_bind_date_time_parameter(size_t index,
|
||||
const ::sqlpp::chrono::microsecond_point* value,
|
||||
bool is_null)
|
||||
{
|
||||
if (_handle->debug)
|
||||
std::cerr << "MySQL debug: binding date_time parameter "
|
||||
<< " at index: " << index << ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||
|
||||
auto& bound_time = _handle->stmt_date_time_param_buffer[index];
|
||||
if (not is_null)
|
||||
{
|
||||
const auto dp = ::sqlpp::chrono::floor<::date::days>(*value);
|
||||
const auto time = date::make_time(*value - dp);
|
||||
const auto ymd = ::date::year_month_day{dp};
|
||||
bound_time.year = static_cast<int>(ymd.year());
|
||||
bound_time.month = static_cast<unsigned>(ymd.month());
|
||||
bound_time.day = static_cast<unsigned>(ymd.day());
|
||||
bound_time.hour = time.hours().count();
|
||||
bound_time.minute = time.minutes().count();
|
||||
bound_time.second = time.seconds().count();
|
||||
bound_time.second_part = time.subseconds().count();
|
||||
if (_handle->debug)
|
||||
std::cerr << "bound values: " << bound_time.year << '-' << bound_time.month << '-' << bound_time.day << 'T'
|
||||
<< bound_time.hour << ':' << bound_time.minute << ':' << bound_time.second << std::endl;
|
||||
}
|
||||
|
||||
_handle->stmt_param_is_null[index] = is_null;
|
||||
MYSQL_BIND& param = _handle->stmt_params[index];
|
||||
param.buffer_type = MYSQL_TYPE_DATETIME;
|
||||
param.buffer = &bound_time;
|
||||
param.buffer_length = sizeof(MYSQL_TIME);
|
||||
param.length = ¶m.buffer_length;
|
||||
param.is_null = &_handle->stmt_param_is_null[index].value;
|
||||
param.is_unsigned = false;
|
||||
param.error = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
12
src/mysql/sqlpp-mysql-config.cmake.in
Normal file
12
src/mysql/sqlpp-mysql-config.cmake.in
Normal file
@ -0,0 +1,12 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
find_dependency(Sqlpp11 REQUIRED)
|
||||
find_dependency(MySQL REQUIRED)
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/sqlpp-mysql-targets.cmake")
|
||||
|
||||
check_required_components(sqlpp-mysql)
|
42
src/mysql/sqlpp_mysql.h
Normal file
42
src/mysql/sqlpp_mysql.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2018 - 2018, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SQLPP_MYSQL_MYSQL_H
|
||||
#define SQLPP_MYSQL_MYSQL_H
|
||||
|
||||
#include <mysql.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace mysql
|
||||
{
|
||||
#if LIBMYSQL_VERSION_ID >= 80000
|
||||
using my_bool = bool;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
26
tests/mysql/CMakeLists.txt
Normal file
26
tests/mysql/CMakeLists.txt
Normal file
@ -0,0 +1,26 @@
|
||||
# Copyright (c) 2021-2021, Roland Bock
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice, this
|
||||
# list of conditions and the following disclaimer in the documentation and/or
|
||||
# other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
add_subdirectory(usage)
|
||||
|
||||
|
25
tests/mysql/usage/CMakeLists.txt
Normal file
25
tests/mysql/usage/CMakeLists.txt
Normal file
@ -0,0 +1,25 @@
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
macro(build_and_run arg)
|
||||
add_executable(Sqlpp11MySQL${arg} ${arg}.cpp)
|
||||
target_link_libraries(Sqlpp11MySQL${arg} PRIVATE sqlpp-mysql)
|
||||
target_link_libraries(Sqlpp11MySQL${arg} PRIVATE Threads::Threads)
|
||||
if(${arg} STREQUAL "JsonTest")
|
||||
target_link_libraries(Sqlpp11MySQL${arg} PRIVATE MySQL::MySQL)
|
||||
endif()
|
||||
if(NOT MSVC)
|
||||
target_compile_options(Sqlpp11MySQL${arg} PRIVATE -Wall -Wextra -pedantic)
|
||||
endif()
|
||||
add_test(${arg} Sqlpp11MySQL${arg})
|
||||
endmacro()
|
||||
|
||||
build_and_run(JsonTest)
|
||||
build_and_run(CustomQuery)
|
||||
build_and_run(DateTimeTest)
|
||||
build_and_run(SampleTest)
|
||||
build_and_run(SelectTest)
|
||||
build_and_run(UnionTest)
|
||||
build_and_run(DynamicSelectTest)
|
||||
build_and_run(MoveConstructorTest)
|
||||
build_and_run(PreparedTest)
|
||||
build_and_run(TruncatedTest)
|
108
tests/mysql/usage/CustomQuery.cpp
Normal file
108
tests/mysql/usage/CustomQuery.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "TabSample.h"
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
#include <sqlpp11/custom_query.h>
|
||||
#include <sqlpp11/mysql/mysql.h>
|
||||
|
||||
SQLPP_ALIAS_PROVIDER(left)
|
||||
SQLPP_ALIAS_PROVIDER(right)
|
||||
namespace
|
||||
{
|
||||
struct on_duplicate_key_update
|
||||
{
|
||||
std::string _serialized;
|
||||
|
||||
template <typename Db, typename Assignment>
|
||||
on_duplicate_key_update(Db& db, Assignment assignment)
|
||||
{
|
||||
typename Db::_serializer_context_t context{db};
|
||||
_serialized = " ON DUPLICATE KEY UPDATE " + serialize(assignment, context).str();
|
||||
}
|
||||
|
||||
template <typename Db, typename Assignment>
|
||||
auto operator()(Db& db, Assignment assignment) -> on_duplicate_key_update&
|
||||
{
|
||||
typename Db::_serializer_context_t context{db};
|
||||
_serialized += ", " + serialize(assignment, context).str();
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto get() const -> sqlpp::verbatim_t<::sqlpp::no_value_t>
|
||||
{
|
||||
return ::sqlpp::verbatim(_serialized);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
const auto tab = TabSample{};
|
||||
|
||||
namespace mysql = sqlpp::mysql;
|
||||
int main()
|
||||
{
|
||||
mysql::global_library_init();
|
||||
|
||||
auto config = std::make_shared<mysql::connection_config>();
|
||||
config->user = "root";
|
||||
config->database = "sqlpp_mysql";
|
||||
config->debug = true;
|
||||
try
|
||||
{
|
||||
mysql::connection db(config);
|
||||
}
|
||||
catch (const sqlpp::exception& e)
|
||||
{
|
||||
std::cerr << "For testing, you'll need to create a database sqlpp_mysql for user root (no password)" << std::endl;
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
mysql::connection db(config);
|
||||
db.execute(R"(DROP TABLE IF EXISTS tab_sample)");
|
||||
db.execute(R"(CREATE TABLE tab_sample (
|
||||
alpha bigint(20) AUTO_INCREMENT,
|
||||
beta varchar(255) DEFAULT NULL,
|
||||
gamma bool DEFAULT NULL,
|
||||
PRIMARY KEY (alpha)
|
||||
))");
|
||||
db.execute(R"(DROP TABLE IF EXISTS tab_foo)");
|
||||
db.execute(R"(CREATE TABLE tab_foo (
|
||||
omega bigint(20) DEFAULT NULL
|
||||
))");
|
||||
|
||||
// Create a MYSQL style custom "insert on duplicate update"
|
||||
db(custom_query(sqlpp::insert_into(tab).set(tab.beta = "sample", tab.gamma = true),
|
||||
on_duplicate_key_update(db, tab.beta = "sample")(db, tab.gamma = false).get()));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
153
tests/mysql/usage/DateTimeTest.cpp
Normal file
153
tests/mysql/usage/DateTimeTest.cpp
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2016, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "TabSample.h"
|
||||
#include <sqlpp11/mysql/mysql.h>
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
const auto library_raii = sqlpp::mysql::scoped_library_initializer_t{};
|
||||
|
||||
namespace
|
||||
{
|
||||
const auto now = ::sqlpp::chrono::floor<::std::chrono::milliseconds>(std::chrono::system_clock::now());
|
||||
const auto today = ::sqlpp::chrono::floor<::sqlpp::chrono::days>(now);
|
||||
const auto yesterday = today - ::sqlpp::chrono::days{1};
|
||||
|
||||
template <typename L, typename R>
|
||||
auto require_equal(int line, const L& l, const R& r) -> void
|
||||
{
|
||||
if (l != r)
|
||||
{
|
||||
std::cerr << line << ": ";
|
||||
serialize(::sqlpp::wrap_operand_t<L>{l}, std::cerr);
|
||||
std::cerr << " != ";
|
||||
serialize(::sqlpp::wrap_operand_t<R>{r}, std::cerr);
|
||||
throw std::runtime_error("Unexpected result");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace mysql = sqlpp::mysql;
|
||||
int main()
|
||||
{
|
||||
auto config = std::make_shared<mysql::connection_config>();
|
||||
config->user = "root";
|
||||
config->database = "sqlpp_mysql";
|
||||
config->debug = true;
|
||||
try
|
||||
{
|
||||
mysql::connection db(config);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "For testing, you'll need to create a database sqlpp_mysql for user root (no password)" << std::endl;
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << "Unknown exception during connect" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using days_type = std::chrono::duration<int, std::ratio<60*60*24>>;
|
||||
|
||||
mysql::connection db(config);
|
||||
db.execute(R"(DROP TABLE IF EXISTS tab_date_time)");
|
||||
db.execute(R"(CREATE TABLE tab_date_time (
|
||||
col_day_point date,
|
||||
col_time_point datetime(3),
|
||||
col_date_time_point datetime DEFAULT CURRENT_TIMESTAMP
|
||||
))");
|
||||
|
||||
const auto tab = TabDateTime{};
|
||||
db(insert_into(tab).default_values());
|
||||
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||
{
|
||||
require_equal(__LINE__, row.colDayPoint.is_null(), true);
|
||||
require_equal(__LINE__, row.colDayPoint.value(), ::sqlpp::chrono::day_point{});
|
||||
require_equal(__LINE__, row.colTimePoint.is_null(), true);
|
||||
require_equal(__LINE__, row.colTimePoint.value(), ::sqlpp::chrono::microsecond_point{});
|
||||
require_equal(__LINE__, std::chrono::time_point_cast<days_type>(row.colDateTimePoint.value()), std::chrono::time_point_cast<days_type>(std::chrono::system_clock::now()));
|
||||
}
|
||||
|
||||
auto statement = db.prepare(select(tab.colDateTimePoint).from(tab).unconditionally());
|
||||
for (const auto& row : db(statement))
|
||||
{
|
||||
require_equal(__LINE__, row.colDateTimePoint.is_null(), false);
|
||||
require_equal(__LINE__, std::chrono::time_point_cast<days_type>(row.colDateTimePoint.value()), std::chrono::time_point_cast<days_type>(std::chrono::system_clock::now()));
|
||||
}
|
||||
|
||||
db(update(tab).set(tab.colDayPoint = today, tab.colTimePoint = now).unconditionally());
|
||||
|
||||
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||
{
|
||||
require_equal(__LINE__, row.colDayPoint.value(), today);
|
||||
require_equal(__LINE__, row.colTimePoint.value(), now);
|
||||
}
|
||||
|
||||
db(update(tab).set(tab.colDayPoint = yesterday, tab.colTimePoint = today).unconditionally());
|
||||
|
||||
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||
{
|
||||
require_equal(__LINE__, row.colDayPoint.value(), yesterday);
|
||||
require_equal(__LINE__, row.colTimePoint.value(), today);
|
||||
}
|
||||
|
||||
auto x = update(tab)
|
||||
.set(tab.colDayPoint = parameter(tab.colDayPoint), tab.colTimePoint = parameter(tab.colTimePoint))
|
||||
.unconditionally();
|
||||
|
||||
auto prepared_update = db.prepare(
|
||||
update(tab)
|
||||
.set(tab.colDayPoint = parameter(tab.colDayPoint), tab.colTimePoint = parameter(tab.colTimePoint))
|
||||
.unconditionally());
|
||||
prepared_update.params.colDayPoint = today;
|
||||
prepared_update.params.colTimePoint = now;
|
||||
std::cout << "---- running prepared update ----" << std::endl;
|
||||
db(prepared_update);
|
||||
std::cout << "---- finished prepared update ----" << std::endl;
|
||||
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||
{
|
||||
require_equal(__LINE__, row.colDayPoint.value(), today);
|
||||
require_equal(__LINE__, row.colTimePoint.value(), now);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << "Unkown exception" << std::endl;
|
||||
}
|
||||
}
|
90
tests/mysql/usage/DynamicSelectTest.cpp
Normal file
90
tests/mysql/usage/DynamicSelectTest.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2016, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "TabSample.h"
|
||||
#include <sqlpp11/alias_provider.h>
|
||||
#include <sqlpp11/functions.h>
|
||||
#include <sqlpp11/insert.h>
|
||||
#include <sqlpp11/mysql/connection.h>
|
||||
#include <sqlpp11/remove.h>
|
||||
#include <sqlpp11/select.h>
|
||||
#include <sqlpp11/transaction.h>
|
||||
#include <sqlpp11/update.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
const auto library_raii = sqlpp::mysql::scoped_library_initializer_t{};
|
||||
|
||||
namespace mysql = sqlpp::mysql;
|
||||
int main()
|
||||
{
|
||||
auto config = std::make_shared<mysql::connection_config>();
|
||||
config->user = "root";
|
||||
config->database = "sqlpp_mysql";
|
||||
config->debug = true;
|
||||
try
|
||||
{
|
||||
mysql::connection db(config);
|
||||
}
|
||||
catch (const sqlpp::exception& e)
|
||||
{
|
||||
std::cerr << "For testing, you'll need to create a database sqlpp_mysql for user root (no password)" << std::endl;
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
mysql::connection db(config);
|
||||
db.execute(R"(DROP TABLE IF EXISTS tab_sample)");
|
||||
db.execute(R"(CREATE TABLE tab_sample (
|
||||
alpha bigint(20) DEFAULT NULL,
|
||||
beta varchar(255) DEFAULT NULL,
|
||||
gamma bool DEFAULT NULL
|
||||
))");
|
||||
|
||||
const auto tab = TabSample{};
|
||||
db(insert_into(tab).set(tab.gamma = true));
|
||||
auto i = insert_into(tab).columns(tab.beta, tab.gamma);
|
||||
i.values.add(tab.beta = "rhabarbertorte", tab.gamma = false);
|
||||
i.values.add(tab.beta = "cheesecake", tab.gamma = false);
|
||||
i.values.add(tab.beta = "kaesekuchen", tab.gamma = true);
|
||||
db(i);
|
||||
|
||||
auto s = dynamic_select(db).dynamic_columns(tab.alpha).from(tab).unconditionally();
|
||||
s.selected_columns.add(tab.beta);
|
||||
|
||||
for (const auto& row : db(s))
|
||||
{
|
||||
std::cerr << "row.alpha: " << row.alpha << ", row.beta: " << row.at("beta") << std::endl;
|
||||
};
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
104
tests/mysql/usage/JsonTest.cpp
Normal file
104
tests/mysql/usage/JsonTest.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2019 - 2019, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <mysql.h>
|
||||
#include <iostream>
|
||||
|
||||
// JSON support only in MYSQL 5.7.8 and later
|
||||
#if !USE_MARIADB && (LIBMYSQL_VERSION_ID < 50708)
|
||||
int main()
|
||||
{
|
||||
std::cerr << "Warning: not testing Json, because the MySQL version id is less than 50708" << std::endl;
|
||||
}
|
||||
#else
|
||||
// JSON support only in MariaDB 10.2.7 and later
|
||||
#if USE_MARIADB && (MARIADB_VERSION_ID < 100207)
|
||||
int main()
|
||||
{
|
||||
std::cerr << "Warning: not testing Json, because the MariaDB version id is less than 100207" << std::endl;
|
||||
}
|
||||
#else
|
||||
|
||||
#include "TabJson.h"
|
||||
#include <sqlpp11/mysql/mysql.h>
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
|
||||
namespace test
|
||||
{
|
||||
SQLPP_ALIAS_PROVIDER(value)
|
||||
}
|
||||
|
||||
namespace mysql = sqlpp::mysql;
|
||||
int main()
|
||||
{
|
||||
mysql::global_library_init();
|
||||
|
||||
auto config = std::make_shared<mysql::connection_config>();
|
||||
config->user = "root";
|
||||
config->database = "sqlpp_mysql";
|
||||
config->debug = true;
|
||||
try
|
||||
{
|
||||
mysql::connection db(config);
|
||||
}
|
||||
catch (const sqlpp::exception& e)
|
||||
{
|
||||
std::cerr << "For testing, you'll need to create a database sqlpp_mysql for user root (no password)" << std::endl;
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
mysql::connection db(config);
|
||||
db.execute(R"(DROP TABLE IF EXISTS tab_json)");
|
||||
db.execute(R"(CREATE TABLE tab_json (
|
||||
data JSON NOT NULL
|
||||
))");
|
||||
|
||||
const auto tab = test::TabJson{};
|
||||
db(insert_into(tab).set(tab.data = R"--({"key" : "value"})--"));
|
||||
|
||||
const auto query =
|
||||
select(sqlpp::verbatim<sqlpp::text>(R"--(JSON_UNQUOTE(JSON_EXTRACT(data, "$.key")))--").as(test::value))
|
||||
.from(tab)
|
||||
.unconditionally();
|
||||
|
||||
auto result = db(query);
|
||||
if (result.empty())
|
||||
throw std::runtime_error{"selection result is empty"};
|
||||
|
||||
const std::string value = result.front().value;
|
||||
|
||||
if (value != "value")
|
||||
throw std::runtime_error{std::string{"unexpected value: "} + value};
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
96
tests/mysql/usage/MoveConstructorTest.cpp
Normal file
96
tests/mysql/usage/MoveConstructorTest.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "TabSample.h"
|
||||
#include <sqlpp11/alias_provider.h>
|
||||
#include <sqlpp11/functions.h>
|
||||
#include <sqlpp11/insert.h>
|
||||
#include <sqlpp11/mysql/connection.h>
|
||||
#include <sqlpp11/remove.h>
|
||||
#include <sqlpp11/select.h>
|
||||
#include <sqlpp11/transaction.h>
|
||||
#include <sqlpp11/update.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
namespace mysql = sqlpp::mysql;
|
||||
int main()
|
||||
{
|
||||
mysql::global_library_init();
|
||||
|
||||
auto config = std::make_shared<mysql::connection_config>();
|
||||
config->user = "root";
|
||||
config->database = "sqlpp_mysql";
|
||||
config->debug = true;
|
||||
try
|
||||
{
|
||||
mysql::connection db(config);
|
||||
}
|
||||
catch (const sqlpp::exception& e)
|
||||
{
|
||||
std::cerr << "For testing, you'll need to create a database sqlpp_mysql for user root (no password)" << std::endl;
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
std::vector<sqlpp::mysql::connection> connections;
|
||||
connections.emplace_back(sqlpp::mysql::connection(config));
|
||||
|
||||
connections.at(0).execute(R"(DROP TABLE IF EXISTS tab_sample)");
|
||||
connections.at(0).execute(R"(CREATE TABLE tab_sample (
|
||||
alpha bigint(20) DEFAULT NULL,
|
||||
beta varchar(255) DEFAULT NULL,
|
||||
gamma bool DEFAULT NULL
|
||||
))");
|
||||
|
||||
connections.at(0).start_transaction();
|
||||
auto db = std::move(connections.at(0));
|
||||
assert(db.is_transaction_active());
|
||||
const auto tab = TabSample{};
|
||||
db(insert_into(tab).set(tab.gamma = true));
|
||||
auto i = insert_into(tab).columns(tab.beta, tab.gamma);
|
||||
i.values.add(tab.beta = "rhabarbertorte", tab.gamma = false);
|
||||
i.values.add(tab.beta = "cheesecake", tab.gamma = false);
|
||||
i.values.add(tab.beta = "kaesekuchen", tab.gamma = true);
|
||||
db(i);
|
||||
|
||||
auto s = dynamic_select(db).dynamic_columns(tab.alpha).from(tab).unconditionally();
|
||||
s.selected_columns.add(tab.beta);
|
||||
|
||||
for (const auto& row : db(s))
|
||||
{
|
||||
std::cerr << "row.alpha: " << row.alpha << ", row.beta: " << row.at("beta") << std::endl;
|
||||
};
|
||||
db.commit_transaction();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
101
tests/mysql/usage/PreparedTest.cpp
Normal file
101
tests/mysql/usage/PreparedTest.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2016, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "TabSample.h"
|
||||
#include <cassert>
|
||||
#include <sqlpp11/alias_provider.h>
|
||||
#include <sqlpp11/functions.h>
|
||||
#include <sqlpp11/insert.h>
|
||||
#include <sqlpp11/mysql/connection.h>
|
||||
#include <sqlpp11/remove.h>
|
||||
#include <sqlpp11/select.h>
|
||||
#include <sqlpp11/transaction.h>
|
||||
#include <sqlpp11/update.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
const auto library_raii = sqlpp::mysql::scoped_library_initializer_t{0, nullptr, nullptr};
|
||||
|
||||
SQLPP_ALIAS_PROVIDER(left)
|
||||
|
||||
namespace sql = sqlpp::mysql;
|
||||
const auto tab = TabSample{};
|
||||
|
||||
void testPreparedStatementResult (sql::connection& db)
|
||||
{
|
||||
auto preparedSelectAll = db.prepare(sqlpp::select(count(tab.alpha)).from(tab).unconditionally());
|
||||
auto preparedUpdateAll = db.prepare(sqlpp::update(tab).set(tab.gamma = false).unconditionally());
|
||||
|
||||
uint32_t count = 0;
|
||||
{
|
||||
// explicit result scope
|
||||
// if results are released update should execute without exception
|
||||
auto result = db(preparedSelectAll);
|
||||
count = result.front().count;
|
||||
}
|
||||
|
||||
db(preparedUpdateAll);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
auto config = std::make_shared<sql::connection_config>();
|
||||
config->user = "root";
|
||||
config->database = "sqlpp_mysql";
|
||||
config->debug = true;
|
||||
try
|
||||
{
|
||||
sql::connection db(config);
|
||||
}
|
||||
catch (const sqlpp::exception& e)
|
||||
{
|
||||
std::cerr << "For testing, you'll need to create a database sqlpp_mysql for user root (no password)" << std::endl;
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
sql::connection db(config);
|
||||
db.execute(R"(DROP TABLE IF EXISTS tab_sample)");
|
||||
db.execute(R"(CREATE TABLE tab_sample (
|
||||
alpha bigint(20) AUTO_INCREMENT,
|
||||
beta varchar(255) DEFAULT NULL,
|
||||
gamma bool DEFAULT NULL,
|
||||
PRIMARY KEY (alpha)
|
||||
))");
|
||||
db.execute(R"(DROP TABLE IF EXISTS tab_foo)");
|
||||
db.execute(R"(CREATE TABLE tab_foo (
|
||||
omega bigint(20) DEFAULT NULL
|
||||
))");
|
||||
|
||||
testPreparedStatementResult(db);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
207
tests/mysql/usage/SampleTest.cpp
Normal file
207
tests/mysql/usage/SampleTest.cpp
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2016, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "TabSample.h"
|
||||
#include <sqlpp11/mysql/mysql.h>
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
SQLPP_ALIAS_PROVIDER(left)
|
||||
SQLPP_ALIAS_PROVIDER(right)
|
||||
|
||||
namespace mysql = sqlpp::mysql;
|
||||
int main()
|
||||
{
|
||||
mysql::global_library_init();
|
||||
|
||||
auto config = std::make_shared<mysql::connection_config>();
|
||||
config->user = "root";
|
||||
config->database = "sqlpp_mysql";
|
||||
config->debug = true;
|
||||
try
|
||||
{
|
||||
mysql::connection db(config);
|
||||
}
|
||||
catch (const sqlpp::exception& e)
|
||||
{
|
||||
std::cerr << "For testing, you'll need to create a database sqlpp_mysql for user root (no password)" << std::endl;
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
mysql::connection db(config);
|
||||
db.execute(R"(DROP TABLE IF EXISTS tab_sample)");
|
||||
db.execute(R"(CREATE TABLE tab_sample (
|
||||
alpha bigint(20) AUTO_INCREMENT,
|
||||
beta varchar(255) DEFAULT NULL,
|
||||
gamma bool DEFAULT NULL,
|
||||
PRIMARY KEY (alpha)
|
||||
))");
|
||||
db.execute(R"(DROP TABLE IF EXISTS tab_foo)");
|
||||
db.execute(R"(CREATE TABLE tab_foo (
|
||||
omega bigint(20) DEFAULT NULL
|
||||
))");
|
||||
|
||||
assert(not db(select(sqlpp::value(false).as(sqlpp::alias::a))).front().a);
|
||||
|
||||
const auto tab = TabSample{};
|
||||
// clear the table
|
||||
db(remove_from(tab).unconditionally());
|
||||
|
||||
// Several ways of ensuring that tab is empty
|
||||
assert(not db(select(exists(select(tab.alpha).from(tab).unconditionally())))
|
||||
.front()
|
||||
.exists); // this is probably the fastest
|
||||
assert(not db(select(count(tab.alpha)).from(tab).unconditionally()).front().count);
|
||||
assert(db(select(tab.alpha).from(tab).unconditionally()).empty());
|
||||
|
||||
// explicit all_of(tab)
|
||||
std::cerr << __FILE__ << ": " << __LINE__ << std::endl;
|
||||
select(all_of(tab)).from(tab);
|
||||
std::cerr << __FILE__ << ": " << __LINE__ << std::endl;
|
||||
db(select(all_of(tab)).from(tab).unconditionally());
|
||||
std::cerr << __FILE__ << ": " << __LINE__ << std::endl;
|
||||
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __LINE__ << std::endl;
|
||||
std::cerr << "row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma
|
||||
<< std::endl;
|
||||
};
|
||||
// insert
|
||||
db(insert_into(tab).default_values());
|
||||
const auto x = select(all_of(tab)).from(tab).unconditionally();
|
||||
const auto y = db.prepare(x);
|
||||
for (const auto& row : db(db.prepare(select(all_of(tab)).from(tab).unconditionally())))
|
||||
{
|
||||
std::cerr << "alpha: " << row.alpha.is_null() << std::endl;
|
||||
std::cerr << "beta: " << row.beta.is_null() << std::endl;
|
||||
std::cerr << "gamma: " << row.gamma.is_null() << std::endl;
|
||||
}
|
||||
db(insert_into(tab).set(tab.beta = "kaesekuchen", tab.gamma = true));
|
||||
db(insert_into(tab).default_values());
|
||||
db(insert_into(tab).set(tab.beta = "", tab.gamma = true));
|
||||
|
||||
// update
|
||||
db(update(tab).set(tab.gamma = false).where(tab.alpha.in(sqlpp::value_list(std::vector<int>{1, 2, 3, 4}))));
|
||||
db(update(tab).set(tab.gamma = true).where(tab.alpha.in(1)));
|
||||
|
||||
// remove
|
||||
db(remove_from(tab).where(tab.alpha == tab.alpha + 3));
|
||||
|
||||
std::cerr << "+++++++++++++++++++++++++++" << std::endl;
|
||||
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||
{
|
||||
std::cerr << __LINE__ << " row.beta: " << row.beta << std::endl;
|
||||
}
|
||||
std::cerr << "+++++++++++++++++++++++++++" << std::endl;
|
||||
decltype(db(select(all_of(tab)).from(tab).unconditionally())) result;
|
||||
result = db(select(all_of(tab)).from(tab).unconditionally());
|
||||
std::cerr << "Accessing a field directly from the result (using the current row): " << result.begin()->alpha
|
||||
<< std::endl;
|
||||
std::cerr << "Can do that again, no problem: " << result.begin()->alpha << std::endl;
|
||||
|
||||
auto tx = start_transaction(db);
|
||||
if (const auto& row =
|
||||
*db(select(all_of(tab), select(max(tab.alpha)).from(tab)).from(tab).unconditionally()).begin())
|
||||
{
|
||||
int a = row.alpha;
|
||||
int m = row.max;
|
||||
std::cerr << __LINE__ << " row.alpha: " << a << ", row.max: " << m << std::endl;
|
||||
}
|
||||
tx.commit();
|
||||
|
||||
TabFoo foo;
|
||||
for (const auto& row : db(select(tab.alpha).from(tab.join(foo).on(tab.alpha == foo.omega)).unconditionally()))
|
||||
{
|
||||
std::cerr << row.alpha << std::endl;
|
||||
}
|
||||
|
||||
for (const auto& row :
|
||||
db(select(tab.alpha).from(tab.left_outer_join(foo).on(tab.alpha == foo.omega)).unconditionally()))
|
||||
{
|
||||
std::cerr << row.alpha << std::endl;
|
||||
}
|
||||
|
||||
auto ps = db.prepare(select(all_of(tab))
|
||||
.from(tab)
|
||||
.where(tab.alpha != parameter(tab.alpha) and tab.beta != parameter(tab.beta) and
|
||||
tab.gamma != parameter(tab.gamma)));
|
||||
ps.params.alpha = 7;
|
||||
ps.params.beta = "wurzelbrunft";
|
||||
ps.params.gamma = true;
|
||||
for (const auto& row : db(ps))
|
||||
{
|
||||
std::cerr << "bound result: alpha: " << row.alpha << std::endl;
|
||||
std::cerr << "bound result: beta: " << row.beta << std::endl;
|
||||
std::cerr << "bound result: gamma: " << row.gamma << std::endl;
|
||||
}
|
||||
|
||||
std::cerr << "--------" << std::endl;
|
||||
ps.params.gamma = "false";
|
||||
for (const auto& row : db(ps))
|
||||
{
|
||||
std::cerr << "bound result: alpha: " << row.alpha << std::endl;
|
||||
std::cerr << "bound result: beta: " << row.beta << std::endl;
|
||||
std::cerr << "bound result: gamma: " << row.gamma << std::endl;
|
||||
}
|
||||
|
||||
std::cerr << "--------" << std::endl;
|
||||
ps.params.beta = "kaesekuchen";
|
||||
for (const auto& row : db(ps))
|
||||
{
|
||||
std::cerr << "bound result: alpha: " << row.alpha << std::endl;
|
||||
std::cerr << "bound result: beta: " << row.beta << std::endl;
|
||||
std::cerr << "bound result: gamma: " << row.gamma << std::endl;
|
||||
}
|
||||
|
||||
auto pi = db.prepare(insert_into(tab).set(tab.beta = parameter(tab.beta), tab.gamma = true));
|
||||
pi.params.beta = "prepared cake";
|
||||
std::cerr << "Inserted: " << db(pi) << std::endl;
|
||||
|
||||
auto pu = db.prepare(update(tab).set(tab.gamma = parameter(tab.gamma)).where(tab.beta == "prepared cake"));
|
||||
pu.params.gamma = false;
|
||||
std::cerr << "Updated: " << db(pu) << std::endl;
|
||||
|
||||
auto pr = db.prepare(remove_from(tab).where(tab.beta != parameter(tab.beta)));
|
||||
pr.params.beta = "prepared cake";
|
||||
std::cerr << "Deleted lines: " << db(pr) << std::endl;
|
||||
|
||||
for (const auto& row : db(select(case_when(tab.gamma).then(tab.alpha).else_(foo.omega).as(tab.alpha))
|
||||
.from(tab.cross_join(foo))
|
||||
.unconditionally()))
|
||||
{
|
||||
std::cerr << row.alpha << std::endl;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
174
tests/mysql/usage/SelectTest.cpp
Normal file
174
tests/mysql/usage/SelectTest.cpp
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2016, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "TabSample.h"
|
||||
#include <cassert>
|
||||
#include <sqlpp11/alias_provider.h>
|
||||
#include <sqlpp11/functions.h>
|
||||
#include <sqlpp11/insert.h>
|
||||
#include <sqlpp11/mysql/connection.h>
|
||||
#include <sqlpp11/remove.h>
|
||||
#include <sqlpp11/select.h>
|
||||
#include <sqlpp11/transaction.h>
|
||||
#include <sqlpp11/update.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
const auto library_raii = sqlpp::mysql::scoped_library_initializer_t{0, nullptr, nullptr};
|
||||
|
||||
SQLPP_ALIAS_PROVIDER(left)
|
||||
|
||||
namespace sql = sqlpp::mysql;
|
||||
const auto tab = TabSample{};
|
||||
|
||||
void testSelectAll(sql::connection& db, int expectedRowCount)
|
||||
{
|
||||
std::cerr << "--------------------------------------" << std::endl;
|
||||
int i = 0;
|
||||
for (const auto& row : db(sqlpp::select(all_of(tab)).from(tab).unconditionally()))
|
||||
{
|
||||
++i;
|
||||
std::cerr << ">>> row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma
|
||||
<< std::endl;
|
||||
assert(i == row.alpha);
|
||||
};
|
||||
assert(i == expectedRowCount);
|
||||
|
||||
auto preparedSelectAll = db.prepare(sqlpp::select(all_of(tab)).from(tab).unconditionally());
|
||||
std::cerr << "--------------------------------------" << std::endl;
|
||||
i = 0;
|
||||
for (const auto& row : db(preparedSelectAll))
|
||||
{
|
||||
++i;
|
||||
std::cerr << ">>> row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma
|
||||
<< std::endl;
|
||||
assert(i == row.alpha);
|
||||
};
|
||||
assert(i == expectedRowCount);
|
||||
|
||||
// Try running the same prepared statement again
|
||||
std::cerr << "--------------------------------------" << std::endl;
|
||||
i = 0;
|
||||
for (const auto& row : db(preparedSelectAll))
|
||||
{
|
||||
++i;
|
||||
std::cerr << ">>> row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma
|
||||
<< std::endl;
|
||||
assert(i == row.alpha);
|
||||
};
|
||||
assert(i == expectedRowCount);
|
||||
std::cerr << "--------------------------------------" << std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
auto config = std::make_shared<sql::connection_config>();
|
||||
config->user = "root";
|
||||
config->database = "sqlpp_mysql";
|
||||
config->debug = true;
|
||||
try
|
||||
{
|
||||
sql::connection db(config);
|
||||
}
|
||||
catch (const sqlpp::exception& e)
|
||||
{
|
||||
std::cerr << "For testing, you'll need to create a database sqlpp_mysql for user root (no password)" << std::endl;
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
sql::connection db(config);
|
||||
db.execute(R"(DROP TABLE IF EXISTS tab_sample)");
|
||||
db.execute(R"(CREATE TABLE tab_sample (
|
||||
alpha bigint(20) AUTO_INCREMENT,
|
||||
beta varchar(255) DEFAULT NULL,
|
||||
gamma bool DEFAULT NULL,
|
||||
PRIMARY KEY (alpha)
|
||||
))");
|
||||
db.execute(R"(DROP TABLE IF EXISTS tab_foo)");
|
||||
db.execute(R"(CREATE TABLE tab_foo (
|
||||
omega bigint(20) DEFAULT NULL
|
||||
))");
|
||||
|
||||
testSelectAll(db, 0);
|
||||
db(insert_into(tab).default_values());
|
||||
testSelectAll(db, 1);
|
||||
db(insert_into(tab).set(tab.gamma = true, tab.beta = "cheesecake"));
|
||||
testSelectAll(db, 2);
|
||||
db(insert_into(tab).set(tab.gamma = true, tab.beta = "cheesecake"));
|
||||
testSelectAll(db, 3);
|
||||
|
||||
// test functions and operators
|
||||
db(select(all_of(tab)).from(tab).where(tab.alpha.is_null()));
|
||||
db(select(all_of(tab)).from(tab).where(tab.alpha.is_not_null()));
|
||||
db(select(all_of(tab)).from(tab).where(tab.alpha.in(1, 2, 3)));
|
||||
db(select(all_of(tab)).from(tab).where(tab.alpha.in(sqlpp::value_list(std::vector<int>{1, 2, 3, 4}))));
|
||||
db(select(all_of(tab)).from(tab).where(tab.alpha.not_in(1, 2, 3)));
|
||||
db(select(all_of(tab)).from(tab).where(tab.alpha.not_in(sqlpp::value_list(std::vector<int>{1, 2, 3, 4}))));
|
||||
db(select(count(tab.alpha)).from(tab).unconditionally());
|
||||
db(select(avg(tab.alpha)).from(tab).unconditionally());
|
||||
db(select(max(tab.alpha)).from(tab).unconditionally());
|
||||
db(select(min(tab.alpha)).from(tab).unconditionally());
|
||||
db(select(exists(select(tab.alpha).from(tab).where(tab.alpha > 7))).from(tab).unconditionally());
|
||||
db(select(all_of(tab)).from(tab).where(tab.alpha == any(select(tab.alpha).from(tab).where(tab.alpha < 3))));
|
||||
db(select(all_of(tab)).from(tab).where(tab.alpha == some(select(tab.alpha).from(tab).where(tab.alpha < 3))));
|
||||
|
||||
db(select(all_of(tab)).from(tab).where(tab.alpha + tab.alpha > 3));
|
||||
db(select(all_of(tab)).from(tab).where((tab.beta + tab.beta) == ""));
|
||||
db(select(all_of(tab)).from(tab).where((tab.beta + tab.beta).like("%'\"%")));
|
||||
|
||||
// insert
|
||||
db(insert_into(tab).set(tab.gamma = true));
|
||||
|
||||
// update
|
||||
db(update(tab).set(tab.gamma = false).where(tab.alpha.in(1)));
|
||||
db(update(tab).set(tab.gamma = false).where(tab.alpha.in(sqlpp::value_list(std::vector<int>{1, 2, 3, 4}))));
|
||||
|
||||
// remove
|
||||
db(remove_from(tab).where(tab.alpha == tab.alpha + 3));
|
||||
|
||||
auto result = db(select(all_of(tab)).from(tab).unconditionally());
|
||||
std::cerr << "Accessing a field directly from the result (using the current row): " << result.begin()->alpha
|
||||
<< std::endl;
|
||||
std::cerr << "Can do that again, no problem: " << result.begin()->alpha << std::endl;
|
||||
|
||||
auto tx = start_transaction(db);
|
||||
if (const auto& row =
|
||||
*db(select(all_of(tab), select(max(tab.alpha)).from(tab)).from(tab).unconditionally()).begin())
|
||||
{
|
||||
int a = row.alpha;
|
||||
int m = row.max;
|
||||
std::cerr << "-----------------------------" << a << ", " << m << std::endl;
|
||||
}
|
||||
tx.commit();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
48
tests/mysql/usage/TabJson.h
Normal file
48
tests/mysql/usage/TabJson.h
Normal file
@ -0,0 +1,48 @@
|
||||
// generated by ../../sqlpp11/scripts/ddl2cpp ../tests/TabJson.sql ../tests/TabJson test
|
||||
#ifndef TEST_TABJSON_H
|
||||
#define TEST_TABJSON_H
|
||||
|
||||
#include <sqlpp11/table.h>
|
||||
#include <sqlpp11/data_types.h>
|
||||
#include <sqlpp11/char_sequence.h>
|
||||
|
||||
namespace test
|
||||
{
|
||||
namespace TabJson_
|
||||
{
|
||||
struct Data
|
||||
{
|
||||
struct _alias_t
|
||||
{
|
||||
static constexpr const char _literal[] = "data";
|
||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||
template<typename T>
|
||||
struct _member_t
|
||||
{
|
||||
T data;
|
||||
T& operator()() { return data; }
|
||||
const T& operator()() const { return data; }
|
||||
};
|
||||
};
|
||||
using _traits = sqlpp::make_traits<sqlpp::text, sqlpp::tag::require_insert>;
|
||||
};
|
||||
} // namespace TabJson_
|
||||
|
||||
struct TabJson: sqlpp::table_t<TabJson,
|
||||
TabJson_::Data>
|
||||
{
|
||||
struct _alias_t
|
||||
{
|
||||
static constexpr const char _literal[] = "tab_json";
|
||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||
template<typename T>
|
||||
struct _member_t
|
||||
{
|
||||
T tabJson;
|
||||
T& operator()() { return tabJson; }
|
||||
const T& operator()() const { return tabJson; }
|
||||
};
|
||||
};
|
||||
};
|
||||
} // namespace test
|
||||
#endif
|
3
tests/mysql/usage/TabJson.sql
Normal file
3
tests/mysql/usage/TabJson.sql
Normal file
@ -0,0 +1,3 @@
|
||||
CREATE TABLE tab_json (
|
||||
data JSON NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
263
tests/mysql/usage/TabSample.h
Normal file
263
tests/mysql/usage/TabSample.h
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SQLPP_TAB_SAMPLE_H
|
||||
#define SQLPP_TAB_SAMPLE_H
|
||||
|
||||
#include <sqlpp11/table.h>
|
||||
#include <sqlpp11/char_sequence.h>
|
||||
#include <sqlpp11/column_types.h>
|
||||
|
||||
namespace TabFoo_
|
||||
{
|
||||
struct Omega
|
||||
{
|
||||
struct _alias_t
|
||||
{
|
||||
static constexpr const char _literal[] = "omega";
|
||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||
template <typename T>
|
||||
struct _member_t
|
||||
{
|
||||
T omega;
|
||||
T& operator()()
|
||||
{
|
||||
return omega;
|
||||
}
|
||||
const T& operator()() const
|
||||
{
|
||||
return omega;
|
||||
}
|
||||
};
|
||||
};
|
||||
using _traits = ::sqlpp::make_traits<::sqlpp::bigint>;
|
||||
};
|
||||
}
|
||||
|
||||
struct TabFoo : sqlpp::table_t<TabFoo, TabFoo_::Omega>
|
||||
{
|
||||
using _value_type = sqlpp::no_value_t;
|
||||
struct _alias_t
|
||||
{
|
||||
static constexpr const char _literal[] = "tab_foo";
|
||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||
template <typename T>
|
||||
struct _member_t
|
||||
{
|
||||
T tabFoo;
|
||||
T& operator()()
|
||||
{
|
||||
return tabFoo;
|
||||
}
|
||||
const T& operator()() const
|
||||
{
|
||||
return tabFoo;
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
namespace TabSample_
|
||||
{
|
||||
struct Alpha
|
||||
{
|
||||
struct _alias_t
|
||||
{
|
||||
static constexpr const char _literal[] = "alpha";
|
||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||
template <typename T>
|
||||
struct _member_t
|
||||
{
|
||||
T alpha;
|
||||
T& operator()()
|
||||
{
|
||||
return alpha;
|
||||
}
|
||||
const T& operator()() const
|
||||
{
|
||||
return alpha;
|
||||
}
|
||||
};
|
||||
};
|
||||
using _traits = ::sqlpp::make_traits<::sqlpp::bigint, ::sqlpp::tag::must_not_insert, ::sqlpp::tag::must_not_update>;
|
||||
};
|
||||
|
||||
struct Beta
|
||||
{
|
||||
struct _alias_t
|
||||
{
|
||||
static constexpr const char _literal[] = "beta";
|
||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||
template <typename T>
|
||||
struct _member_t
|
||||
{
|
||||
T beta;
|
||||
T& operator()()
|
||||
{
|
||||
return beta;
|
||||
}
|
||||
const T& operator()() const
|
||||
{
|
||||
return beta;
|
||||
}
|
||||
};
|
||||
};
|
||||
using _traits = ::sqlpp::make_traits<::sqlpp::varchar, ::sqlpp::tag::must_not_update, ::sqlpp::tag::can_be_null>;
|
||||
};
|
||||
|
||||
struct Gamma
|
||||
{
|
||||
struct _alias_t
|
||||
{
|
||||
static constexpr const char _literal[] = "gamma";
|
||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||
template <typename T>
|
||||
struct _member_t
|
||||
{
|
||||
T gamma;
|
||||
T& operator()()
|
||||
{
|
||||
return gamma;
|
||||
}
|
||||
const T& operator()() const
|
||||
{
|
||||
return gamma;
|
||||
}
|
||||
};
|
||||
};
|
||||
using _traits = ::sqlpp::make_traits<::sqlpp::boolean>;
|
||||
};
|
||||
}
|
||||
|
||||
struct TabSample : sqlpp::table_t<TabSample, TabSample_::Alpha, TabSample_::Beta, TabSample_::Gamma>
|
||||
{
|
||||
using _value_type = sqlpp::no_value_t;
|
||||
struct _alias_t
|
||||
{
|
||||
static constexpr const char _literal[] = "tab_sample";
|
||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||
template <typename T>
|
||||
struct _member_t
|
||||
{
|
||||
T tabSample;
|
||||
T& operator()()
|
||||
{
|
||||
return tabSample;
|
||||
}
|
||||
const T& operator()() const
|
||||
{
|
||||
return tabSample;
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
namespace TabDateTime_
|
||||
{
|
||||
struct ColDayPoint
|
||||
{
|
||||
struct _alias_t
|
||||
{
|
||||
static constexpr const char _literal[] = "col_day_point";
|
||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||
template <typename T>
|
||||
struct _member_t
|
||||
{
|
||||
T colDayPoint;
|
||||
T& operator()()
|
||||
{
|
||||
return colDayPoint;
|
||||
}
|
||||
const T& operator()() const
|
||||
{
|
||||
return colDayPoint;
|
||||
}
|
||||
};
|
||||
};
|
||||
using _traits = sqlpp::make_traits<sqlpp::day_point, sqlpp::tag::can_be_null>;
|
||||
};
|
||||
struct ColTimePoint
|
||||
{
|
||||
struct _alias_t
|
||||
{
|
||||
static constexpr const char _literal[] = "col_time_point";
|
||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||
template <typename T>
|
||||
struct _member_t
|
||||
{
|
||||
T colTimePoint;
|
||||
T& operator()()
|
||||
{
|
||||
return colTimePoint;
|
||||
}
|
||||
const T& operator()() const
|
||||
{
|
||||
return colTimePoint;
|
||||
}
|
||||
};
|
||||
};
|
||||
using _traits = sqlpp::make_traits<sqlpp::time_point, sqlpp::tag::can_be_null>;
|
||||
};
|
||||
struct ColDateTimePoint
|
||||
{
|
||||
struct _alias_t
|
||||
{
|
||||
static constexpr const char _literal[] = "col_date_time_point";
|
||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||
template<typename T>
|
||||
struct _member_t
|
||||
{
|
||||
T colDateTimePoint;
|
||||
T& operator()() { return colDateTimePoint; }
|
||||
const T& operator()() const { return colDateTimePoint; }
|
||||
};
|
||||
};
|
||||
using _traits = sqlpp::make_traits<sqlpp::time_point>;
|
||||
};
|
||||
}
|
||||
|
||||
struct TabDateTime : sqlpp::table_t<TabDateTime, TabDateTime_::ColDayPoint, TabDateTime_::ColTimePoint, TabDateTime_::ColDateTimePoint>
|
||||
{
|
||||
struct _alias_t
|
||||
{
|
||||
static constexpr const char _literal[] = "tab_date_time";
|
||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||
template <typename T>
|
||||
struct _member_t
|
||||
{
|
||||
T tabDateTime;
|
||||
T& operator()()
|
||||
{
|
||||
return tabDateTime;
|
||||
}
|
||||
const T& operator()() const
|
||||
{
|
||||
return tabDateTime;
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
5
tests/mysql/usage/TabSample.sql
Normal file
5
tests/mysql/usage/TabSample.sql
Normal file
@ -0,0 +1,5 @@
|
||||
CREATE TABLE tab_sample (
|
||||
alpha bigint(20) DEFAULT NULL AUTO_INCREMENT,
|
||||
beta tinyint(1) DEFAULT NULL,
|
||||
gamma varchar(255) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
108
tests/mysql/usage/TruncatedTest.cpp
Normal file
108
tests/mysql/usage/TruncatedTest.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2016, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "TabSample.h"
|
||||
#include <cassert>
|
||||
#include <sqlpp11/alias_provider.h>
|
||||
#include <sqlpp11/functions.h>
|
||||
#include <sqlpp11/insert.h>
|
||||
#include <sqlpp11/mysql/connection.h>
|
||||
#include <sqlpp11/remove.h>
|
||||
#include <sqlpp11/select.h>
|
||||
#include <sqlpp11/transaction.h>
|
||||
#include <sqlpp11/update.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
const auto library_raii = sqlpp::mysql::scoped_library_initializer_t{0, nullptr, nullptr};
|
||||
|
||||
namespace sql = sqlpp::mysql;
|
||||
const auto tab = TabSample{};
|
||||
|
||||
int main()
|
||||
{
|
||||
auto config = std::make_shared<sql::connection_config>();
|
||||
config->user = "root";
|
||||
config->database = "sqlpp_mysql";
|
||||
config->debug = true;
|
||||
config->charset = "utf8";
|
||||
try
|
||||
{
|
||||
sql::connection db(config);
|
||||
}
|
||||
catch (const sqlpp::exception& e)
|
||||
{
|
||||
std::cerr << "For testing, you'll need to create a database sqlpp_mysql for user root (no password)" << std::endl;
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
sql::connection db(config);
|
||||
db.execute(R"(DROP TABLE IF EXISTS tab_sample)");
|
||||
db.execute(R"(CREATE TABLE tab_sample (
|
||||
alpha bigint(20) AUTO_INCREMENT,
|
||||
beta varchar(255) DEFAULT NULL,
|
||||
gamma bool DEFAULT NULL,
|
||||
PRIMARY KEY (alpha)
|
||||
))");
|
||||
db.execute(R"(DROP TABLE IF EXISTS tab_foo)");
|
||||
db.execute(R"(CREATE TABLE tab_foo (
|
||||
omega bigint(20) DEFAULT NULL
|
||||
))");
|
||||
|
||||
db(insert_into(tab).set(tab.gamma = true, tab.beta = "cheese"));
|
||||
db(insert_into(tab).set(tab.gamma = true, tab.beta = "cheesecake"));
|
||||
|
||||
{
|
||||
for (const auto& row : db(db.prepare(sqlpp::select(all_of(tab)).from(tab).unconditionally())))
|
||||
{
|
||||
std::cerr << ">>> row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto result = db(db.prepare(sqlpp::select(all_of(tab)).from(tab).where(tab.alpha == 1).limit(1u)));
|
||||
auto& row = result.front();
|
||||
|
||||
std::cerr << ">>> row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma << std::endl;
|
||||
assert(row.beta == "cheese");
|
||||
}
|
||||
|
||||
{
|
||||
auto result = db(db.prepare(sqlpp::select(all_of(tab)).from(tab).where(tab.alpha == 2).limit(1u)));
|
||||
auto& row = result.front();
|
||||
|
||||
std::cerr << ">>> row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma << std::endl;
|
||||
assert(row.beta == "cheesecake");
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
81
tests/mysql/usage/UnionTest.cpp
Normal file
81
tests/mysql/usage/UnionTest.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - 2016, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "TabSample.h"
|
||||
#include <sqlpp11/mysql/connection.h>
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
const auto library_raii = sqlpp::mysql::scoped_library_initializer_t{0, nullptr, nullptr};
|
||||
|
||||
namespace sql = sqlpp::mysql;
|
||||
const auto tab = TabSample{};
|
||||
|
||||
int main()
|
||||
{
|
||||
auto config = std::make_shared<sql::connection_config>();
|
||||
config->user = "root";
|
||||
config->database = "sqlpp_mysql";
|
||||
config->debug = true;
|
||||
try
|
||||
{
|
||||
sql::connection db(config);
|
||||
}
|
||||
catch (const sqlpp::exception& e)
|
||||
{
|
||||
std::cerr << "For testing, you'll need to create a database sqlpp_mysql for user root (no password)" << std::endl;
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
sql::connection db(config);
|
||||
db.execute(R"(DROP TABLE IF EXISTS tab_sample)");
|
||||
db.execute(R"(CREATE TABLE tab_sample (
|
||||
alpha bigint(20) AUTO_INCREMENT,
|
||||
beta bool DEFAULT NULL,
|
||||
gamma varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (alpha)
|
||||
))");
|
||||
|
||||
auto u = select(all_of(tab)).from(tab).unconditionally().union_all(select(all_of(tab)).from(tab).unconditionally());
|
||||
|
||||
for (const auto& row : db(u))
|
||||
{
|
||||
std::cout << row.alpha << row.beta << row.gamma << std::endl;
|
||||
}
|
||||
|
||||
for (const auto& row : db(u.union_distinct(select(all_of(tab)).from(tab).unconditionally())))
|
||||
{
|
||||
std::cout << row.alpha << row.beta << row.gamma << std::endl;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user