mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Cleanup the code of the MySQL connector (#511)
* Move the method definitions for sqlpp::postgresql::detail::statement_handle_t inside the class. * Move the method definitions for sqlpp::postgresql::detail::prepared_statement_handle_t inside the class. * Move the method definitions for sqlpp::postgresql::prepared_statement_t inside the class. * Move the method definitions for sqlpp::postgresql::::Result inside the class. * Remove superfluous inline specifier from the in-class method definitions of sqlpp::postgresql::Result. * Remove unused method declaration sqlpp::postgresql::Result::hasError() * Move the method definitions for sqlpp::postgresql::bind_result_t inside the class. * Move the method definitions for sqlpp::postgresql::connection_base inside the class. * Add a comment explaining why sqlpp::postgresql::context_t::escape() is defined out-of-class. * Remove incorrect comment about forward declaration * Remove a superfluous function that forwards the call to PQFinish(). * Replace "std::string" parameters with "const std::string&". * Remove superfluous detail:: namespace qualification. * Rename class/struct types, variables and functions from CamelCase to snake_case.
This commit is contained in:
parent
c03ac660ee
commit
d800f4d6fa
@ -56,11 +56,55 @@ namespace sqlpp
|
|||||||
private:
|
private:
|
||||||
std::shared_ptr<detail::statement_handle_t> _handle;
|
std::shared_ptr<detail::statement_handle_t> _handle;
|
||||||
|
|
||||||
bool next_impl();
|
bool next_impl()
|
||||||
|
{
|
||||||
|
if (_handle->debug())
|
||||||
|
{
|
||||||
|
std::cerr << "PostgreSQL debug: accessing next row of handle at " << _handle.get() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch total amount
|
||||||
|
if (_handle->total_count == 0U)
|
||||||
|
{
|
||||||
|
_handle->total_count = _handle->result.records_size();
|
||||||
|
if (_handle->total_count == 0U)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Next row
|
||||||
|
if (_handle->count < (_handle->total_count - 1))
|
||||||
|
{
|
||||||
|
_handle->count++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Really needed?
|
||||||
|
if (_handle->fields == 0U)
|
||||||
|
{
|
||||||
|
_handle->fields = _handle->result.field_count();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bind_result_t() = default;
|
bind_result_t() = default;
|
||||||
bind_result_t(const std::shared_ptr<detail::statement_handle_t>& handle);
|
|
||||||
|
bind_result_t(const std::shared_ptr<detail::statement_handle_t>& handle) : _handle(handle)
|
||||||
|
{
|
||||||
|
if (this->_handle && this->_handle->debug())
|
||||||
|
{
|
||||||
|
// cerr
|
||||||
|
std::cerr << "PostgreSQL debug: constructing bind result, using handle at: " << this->_handle.get()
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bind_result_t(const bind_result_t&) = delete;
|
bind_result_t(const bind_result_t&) = delete;
|
||||||
bind_result_t(bind_result_t&&) = default;
|
bind_result_t(bind_result_t&&) = default;
|
||||||
bind_result_t& operator=(const bind_result_t&) = delete;
|
bind_result_t& operator=(const bind_result_t&) = delete;
|
||||||
@ -98,66 +142,7 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_boolean_result(size_t index, signed char* value, bool* is_null);
|
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** value, 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 _bind_time_of_day_result(size_t index, ::std::chrono::microseconds* value, bool* is_null);
|
|
||||||
void _bind_blob_result(size_t index, const uint8_t** value, size_t* len);
|
|
||||||
|
|
||||||
int size() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bind_result_t::bind_result_t(const std::shared_ptr<detail::statement_handle_t>& handle) : _handle(handle)
|
|
||||||
{
|
|
||||||
if (this->_handle && this->_handle->debug())
|
|
||||||
{
|
|
||||||
// cerr
|
|
||||||
std::cerr << "PostgreSQL debug: constructing bind result, using handle at: " << this->_handle.get()
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool bind_result_t::next_impl()
|
|
||||||
{
|
|
||||||
if (_handle->debug())
|
|
||||||
{
|
|
||||||
std::cerr << "PostgreSQL debug: accessing next row of handle at " << _handle.get() << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch total amount
|
|
||||||
if (_handle->totalCount == 0U)
|
|
||||||
{
|
|
||||||
_handle->totalCount = _handle->result.records_size();
|
|
||||||
if (_handle->totalCount == 0U)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Next row
|
|
||||||
if (_handle->count < (_handle->totalCount - 1))
|
|
||||||
{
|
|
||||||
_handle->count++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Really needed?
|
|
||||||
if (_handle->fields == 0U)
|
|
||||||
{
|
|
||||||
_handle->fields = _handle->result.field_count();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void bind_result_t::_bind_boolean_result(size_t _index, signed char* value, bool* is_null)
|
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
auto index = static_cast<int>(_index);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
@ -165,11 +150,11 @@ namespace sqlpp
|
|||||||
std::cerr << "PostgreSQL debug: binding boolean result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: binding boolean result at index: " << index << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
*is_null = _handle->result.isNull(_handle->count, index);
|
*is_null = _handle->result.is_null(_handle->count, index);
|
||||||
*value = _handle->result.getBoolValue(_handle->count, index);
|
*value = _handle->result.get_bool_value(_handle->count, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void bind_result_t::_bind_floating_point_result(size_t _index, double* value, bool* is_null)
|
void _bind_floating_point_result(size_t _index, double* value, bool* is_null)
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
auto index = static_cast<int>(_index);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
@ -177,11 +162,11 @@ namespace sqlpp
|
|||||||
std::cerr << "PostgreSQL debug: binding floating_point result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: binding floating_point result at index: " << index << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
*is_null = _handle->result.isNull(_handle->count, index);
|
*is_null = _handle->result.is_null(_handle->count, index);
|
||||||
*value = _handle->result.getDoubleValue(_handle->count, index);
|
*value = _handle->result.get_double_value(_handle->count, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void bind_result_t::_bind_integral_result(size_t _index, int64_t* value, bool* is_null)
|
void _bind_integral_result(size_t _index, int64_t* value, bool* is_null)
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
auto index = static_cast<int>(_index);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
@ -189,11 +174,11 @@ namespace sqlpp
|
|||||||
std::cerr << "PostgreSQL debug: binding integral result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: binding integral result at index: " << index << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
*is_null = _handle->result.isNull(_handle->count, index);
|
*is_null = _handle->result.is_null(_handle->count, index);
|
||||||
*value = _handle->result.getInt64Value(_handle->count, index);
|
*value = _handle->result.get_int64_value(_handle->count, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void bind_result_t::_bind_unsigned_integral_result(size_t _index, uint64_t* value, bool* is_null)
|
void _bind_unsigned_integral_result(size_t _index, uint64_t* value, bool* is_null)
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
auto index = static_cast<int>(_index);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
@ -201,11 +186,11 @@ namespace sqlpp
|
|||||||
std::cerr << "PostgreSQL debug: binding unsigned integral result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: binding unsigned integral result at index: " << index << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
*is_null = _handle->result.isNull(_handle->count, index);
|
*is_null = _handle->result.is_null(_handle->count, index);
|
||||||
*value = _handle->result.getUInt64Value(_handle->count, index);
|
*value = _handle->result.get_uint64_value(_handle->count, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void bind_result_t::_bind_text_result(size_t _index, const char** value, size_t* len)
|
void _bind_text_result(size_t _index, const char** value, size_t* len)
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
auto index = static_cast<int>(_index);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
@ -213,14 +198,14 @@ namespace sqlpp
|
|||||||
std::cerr << "PostgreSQL debug: binding text result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: binding text result at index: " << index << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_handle->result.isNull(_handle->count, index))
|
if (_handle->result.is_null(_handle->count, index))
|
||||||
{
|
{
|
||||||
*value = nullptr;
|
*value = nullptr;
|
||||||
*len = 0;
|
*len = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*value = _handle->result.getCharPtrValue(_handle->count, index);
|
*value = _handle->result.get_char_ptr_value(_handle->count, index);
|
||||||
*len = static_cast<size_t>(_handle->result.length(_handle->count, index));
|
*len = static_cast<size_t>(_handle->result.length(_handle->count, index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -233,8 +218,7 @@ namespace sqlpp
|
|||||||
// 1992-10-10 01:02:03-06:30 - for some timezones with non-hour offset
|
// 1992-10-10 01:02:03-06:30 - for some timezones with non-hour offset
|
||||||
// 1900-01-01 - date only
|
// 1900-01-01 - date only
|
||||||
// we do not support time-only values !
|
// we do not support time-only values !
|
||||||
|
void _bind_date_result(size_t _index, ::sqlpp::chrono::day_point* value, bool* is_null)
|
||||||
inline void bind_result_t::_bind_date_result(size_t _index, ::sqlpp::chrono::day_point* value, bool* is_null)
|
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
auto index = static_cast<int>(_index);
|
||||||
|
|
||||||
@ -243,11 +227,11 @@ namespace sqlpp
|
|||||||
std::cerr << "PostgreSQL debug: binding date result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: binding date result at index: " << index << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
*is_null = _handle->result.isNull(_handle->count, index);
|
*is_null = _handle->result.is_null(_handle->count, index);
|
||||||
|
|
||||||
if (!(*is_null))
|
if (!(*is_null))
|
||||||
{
|
{
|
||||||
const auto date_string = _handle->result.getCharPtrValue(_handle->count, index);
|
const auto date_string = _handle->result.get_char_ptr_value(_handle->count, index);
|
||||||
|
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
@ -277,7 +261,7 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// always returns UTC time for timestamp with time zone
|
// always returns UTC time for timestamp with time zone
|
||||||
inline void bind_result_t::_bind_date_time_result(size_t _index, ::sqlpp::chrono::microsecond_point* value, bool* is_null)
|
void _bind_date_time_result(size_t _index, ::sqlpp::chrono::microsecond_point* value, bool* is_null)
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
auto index = static_cast<int>(_index);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
@ -285,11 +269,11 @@ namespace sqlpp
|
|||||||
std::cerr << "PostgreSQL debug: binding date_time result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: binding date_time result at index: " << index << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
*is_null = _handle->result.isNull(_handle->count, index);
|
*is_null = _handle->result.is_null(_handle->count, index);
|
||||||
|
|
||||||
if (!(*is_null))
|
if (!(*is_null))
|
||||||
{
|
{
|
||||||
const auto date_string = _handle->result.getCharPtrValue(_handle->count, index);
|
const auto date_string = _handle->result.get_char_ptr_value(_handle->count, index);
|
||||||
|
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
@ -333,7 +317,7 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// always returns UTC time for time with time zone
|
// always returns UTC time for time with time zone
|
||||||
inline void bind_result_t::_bind_time_of_day_result(size_t _index, ::std::chrono::microseconds* value, bool* is_null)
|
void _bind_time_of_day_result(size_t _index, ::std::chrono::microseconds* value, bool* is_null)
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
auto index = static_cast<int>(_index);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
@ -341,11 +325,11 @@ namespace sqlpp
|
|||||||
std::cerr << "PostgreSQL debug: binding time result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: binding time result at index: " << index << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
*is_null = _handle->result.isNull(_handle->count, index);
|
*is_null = _handle->result.is_null(_handle->count, index);
|
||||||
|
|
||||||
if (!(*is_null))
|
if (!(*is_null))
|
||||||
{
|
{
|
||||||
const auto time_string = _handle->result.getCharPtrValue(_handle->count, index);
|
const auto time_string = _handle->result.get_char_ptr_value(_handle->count, index);
|
||||||
|
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
@ -382,30 +366,30 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void bind_result_t::_bind_blob_result(size_t _index, const uint8_t** value, size_t* len)
|
void _bind_blob_result(size_t _index, const uint8_t** value, size_t* len)
|
||||||
{
|
{
|
||||||
|
|
||||||
auto index = static_cast<int>(_index);
|
auto index = static_cast<int>(_index);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding blob result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: binding blob result at index: " << index << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_handle->result.isNull(_handle->count, index))
|
if (_handle->result.is_null(_handle->count, index))
|
||||||
{
|
{
|
||||||
*value = nullptr;
|
*value = nullptr;
|
||||||
*len = 0;
|
*len = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*value = _handle->result.getBlobValue(_handle->count, index);
|
*value = _handle->result.get_blob_value(_handle->count, index);
|
||||||
*len = static_cast<size_t>(_handle->result.length(_handle->count, index));
|
*len = static_cast<size_t>(_handle->result.length(_handle->count, index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int bind_result_t::size() const
|
int size() const
|
||||||
{
|
{
|
||||||
return _handle->result.records_size();
|
return _handle->result.records_size();
|
||||||
}
|
}
|
||||||
|
};
|
||||||
} // namespace postgresql
|
} // namespace postgresql
|
||||||
} // namespace sqlpp
|
} // namespace sqlpp
|
||||||
|
@ -62,10 +62,9 @@ namespace sqlpp
|
|||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
// Forward declaration
|
|
||||||
inline std::unique_ptr<detail::prepared_statement_handle_t> prepare_statement(std::unique_ptr<connection_handle>& handle,
|
inline std::unique_ptr<detail::prepared_statement_handle_t> prepare_statement(std::unique_ptr<connection_handle>& handle,
|
||||||
const std::string& stmt,
|
const std::string& stmt,
|
||||||
const size_t& paramCount)
|
const size_t& param_count)
|
||||||
{
|
{
|
||||||
if (handle->config->debug)
|
if (handle->config->debug)
|
||||||
{
|
{
|
||||||
@ -73,7 +72,7 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
return std::unique_ptr<detail::prepared_statement_handle_t>(new detail::prepared_statement_handle_t
|
return std::unique_ptr<detail::prepared_statement_handle_t>(new detail::prepared_statement_handle_t
|
||||||
(*handle, stmt, paramCount));
|
(*handle, stmt, param_count));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void execute_prepared_statement(std::unique_ptr<connection_handle>& handle, std::shared_ptr<detail::prepared_statement_handle_t>& prepared)
|
inline void execute_prepared_statement(std::unique_ptr<connection_handle>& handle, std::shared_ptr<detail::prepared_statement_handle_t>& prepared)
|
||||||
@ -144,18 +143,67 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// direct execution
|
// direct execution
|
||||||
bind_result_t select_impl(const std::string& stmt);
|
bind_result_t select_impl(const std::string& stmt)
|
||||||
size_t insert_impl(const std::string& stmt);
|
{
|
||||||
size_t update_impl(const std::string& stmt);
|
return execute(stmt);
|
||||||
size_t remove_impl(const std::string& stmt);
|
}
|
||||||
|
|
||||||
|
size_t insert_impl(const std::string& stmt)
|
||||||
|
{
|
||||||
|
return static_cast<size_t>(execute(stmt)->result.affected_rows());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t update_impl(const std::string& stmt)
|
||||||
|
{
|
||||||
|
return static_cast<size_t>(execute(stmt)->result.affected_rows());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t remove_impl(const std::string& stmt)
|
||||||
|
{
|
||||||
|
return static_cast<size_t>(execute(stmt)->result.affected_rows());
|
||||||
|
}
|
||||||
|
|
||||||
// prepared execution
|
// prepared execution
|
||||||
prepared_statement_t prepare_impl(const std::string& stmt, const size_t& paramCount);
|
prepared_statement_t prepare_impl(const std::string& stmt, const size_t& param_count)
|
||||||
bind_result_t run_prepared_select_impl(prepared_statement_t& prep);
|
{
|
||||||
size_t run_prepared_execute_impl(prepared_statement_t& prep);
|
validate_connection_handle();
|
||||||
size_t run_prepared_insert_impl(prepared_statement_t& prep);
|
return {prepare_statement(_handle, stmt, param_count)};
|
||||||
size_t run_prepared_update_impl(prepared_statement_t& prep);
|
}
|
||||||
size_t run_prepared_remove_impl(prepared_statement_t& prep);
|
|
||||||
|
bind_result_t run_prepared_select_impl(prepared_statement_t& prep)
|
||||||
|
{
|
||||||
|
validate_connection_handle();
|
||||||
|
execute_prepared_statement(_handle, prep._handle);
|
||||||
|
return {prep._handle};
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t run_prepared_execute_impl(prepared_statement_t& prep)
|
||||||
|
{
|
||||||
|
validate_connection_handle();
|
||||||
|
execute_prepared_statement(_handle, prep._handle);
|
||||||
|
return static_cast<size_t>(prep._handle->result.affected_rows());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t run_prepared_insert_impl(prepared_statement_t& prep)
|
||||||
|
{
|
||||||
|
validate_connection_handle();
|
||||||
|
execute_prepared_statement(_handle, prep._handle);
|
||||||
|
return static_cast<size_t>(prep._handle->result.affected_rows());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t run_prepared_update_impl(prepared_statement_t& prep)
|
||||||
|
{
|
||||||
|
validate_connection_handle();
|
||||||
|
execute_prepared_statement(_handle, prep._handle);
|
||||||
|
return static_cast<size_t>(prep._handle->result.affected_rows());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t run_prepared_remove_impl(prepared_statement_t& prep)
|
||||||
|
{
|
||||||
|
validate_connection_handle();
|
||||||
|
execute_prepared_statement(_handle, prep._handle);
|
||||||
|
return static_cast<size_t>(prep._handle->result.affected_rows());
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using _connection_base_t = connection_base;
|
using _connection_base_t = connection_base;
|
||||||
@ -284,7 +332,20 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
std::shared_ptr<detail::statement_handle_t> execute(const std::string& command);
|
std::shared_ptr<detail::statement_handle_t> execute(const std::string& stmt)
|
||||||
|
{
|
||||||
|
validate_connection_handle();
|
||||||
|
if (_handle->config->debug)
|
||||||
|
{
|
||||||
|
std::cerr << "PostgreSQL debug: executing: " << stmt << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = std::make_shared<detail::statement_handle_t>(*_handle);
|
||||||
|
result->result = PQexec(native_handle(), stmt.c_str());
|
||||||
|
result->valid = true;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename Execute,
|
typename Execute,
|
||||||
@ -313,7 +374,19 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// escape argument
|
// escape argument
|
||||||
std::string escape(const std::string& s) const;
|
// TODO: Fix escaping.
|
||||||
|
std::string escape(const std::string& s) const
|
||||||
|
{
|
||||||
|
validate_connection_handle();
|
||||||
|
// Escape strings
|
||||||
|
std::string result;
|
||||||
|
result.resize((s.size() * 2) + 1);
|
||||||
|
|
||||||
|
int err;
|
||||||
|
size_t length = PQescapeStringConn(native_handle(), &result[0], s.c_str(), s.size(), &err);
|
||||||
|
result.resize(length);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
//! call run on the argument
|
//! call run on the argument
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -348,127 +421,7 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! set the default transaction isolation level to use for new transactions
|
//! set the default transaction isolation level to use for new transactions
|
||||||
void set_default_isolation_level(isolation_level level);
|
void set_default_isolation_level(isolation_level level)
|
||||||
|
|
||||||
//! get the currently set default transaction isolation level
|
|
||||||
isolation_level get_default_isolation_level();
|
|
||||||
|
|
||||||
//! create savepoint
|
|
||||||
void savepoint(const std::string& name);
|
|
||||||
|
|
||||||
//! ROLLBACK TO SAVEPOINT
|
|
||||||
void rollback_to_savepoint(const std::string& name);
|
|
||||||
|
|
||||||
//! release_savepoint
|
|
||||||
void release_savepoint(const std::string& name);
|
|
||||||
|
|
||||||
//! start transaction
|
|
||||||
void start_transaction(isolation_level level = isolation_level::undefined);
|
|
||||||
|
|
||||||
//! commit transaction (or throw transaction if transaction has
|
|
||||||
// finished already)
|
|
||||||
void commit_transaction();
|
|
||||||
|
|
||||||
//! rollback transaction
|
|
||||||
void rollback_transaction(bool report);
|
|
||||||
|
|
||||||
//! report rollback failure
|
|
||||||
void report_rollback_failure(const std::string& message) noexcept;
|
|
||||||
|
|
||||||
//! get the last inserted id for a certain table
|
|
||||||
uint64_t last_insert_id(const std::string& table, const std::string& fieldname);
|
|
||||||
|
|
||||||
::PGconn* native_handle() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
_handle_ptr_t _handle;
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
connection_base() = default;
|
|
||||||
connection_base(_handle_ptr_t&& handle) : _handle{std::move(handle)}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline std::shared_ptr<detail::statement_handle_t> connection_base::execute(const std::string& stmt)
|
|
||||||
{
|
|
||||||
validate_connection_handle();
|
|
||||||
if (_handle->config->debug)
|
|
||||||
{
|
|
||||||
std::cerr << "PostgreSQL debug: executing: " << stmt << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto result = std::make_shared<detail::statement_handle_t>(*_handle);
|
|
||||||
result->result = PQexec(native_handle(), stmt.c_str());
|
|
||||||
result->valid = true;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// direct execution
|
|
||||||
inline bind_result_t connection_base::select_impl(const std::string& stmt)
|
|
||||||
{
|
|
||||||
return execute(stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t connection_base::insert_impl(const std::string& stmt)
|
|
||||||
{
|
|
||||||
return static_cast<size_t>(execute(stmt)->result.affected_rows());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t connection_base::update_impl(const std::string& stmt)
|
|
||||||
{
|
|
||||||
return static_cast<size_t>(execute(stmt)->result.affected_rows());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t connection_base::remove_impl(const std::string& stmt)
|
|
||||||
{
|
|
||||||
return static_cast<size_t>(execute(stmt)->result.affected_rows());
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepared execution
|
|
||||||
inline prepared_statement_t connection_base::prepare_impl(const std::string& stmt, const size_t& paramCount)
|
|
||||||
{
|
|
||||||
validate_connection_handle();
|
|
||||||
return {prepare_statement(_handle, stmt, paramCount)};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bind_result_t connection_base::run_prepared_select_impl(prepared_statement_t& prep)
|
|
||||||
{
|
|
||||||
validate_connection_handle();
|
|
||||||
execute_prepared_statement(_handle, prep._handle);
|
|
||||||
return {prep._handle};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t connection_base::run_prepared_execute_impl(prepared_statement_t& prep)
|
|
||||||
{
|
|
||||||
validate_connection_handle();
|
|
||||||
execute_prepared_statement(_handle, prep._handle);
|
|
||||||
return static_cast<size_t>(prep._handle->result.affected_rows());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t connection_base::run_prepared_insert_impl(prepared_statement_t& prep)
|
|
||||||
{
|
|
||||||
validate_connection_handle();
|
|
||||||
execute_prepared_statement(_handle, prep._handle);
|
|
||||||
return static_cast<size_t>(prep._handle->result.affected_rows());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t connection_base::run_prepared_update_impl(prepared_statement_t& prep)
|
|
||||||
{
|
|
||||||
validate_connection_handle();
|
|
||||||
execute_prepared_statement(_handle, prep._handle);
|
|
||||||
return static_cast<size_t>(prep._handle->result.affected_rows());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t connection_base::run_prepared_remove_impl(prepared_statement_t& prep)
|
|
||||||
{
|
|
||||||
validate_connection_handle();
|
|
||||||
execute_prepared_statement(_handle, prep._handle);
|
|
||||||
return static_cast<size_t>(prep._handle->result.affected_rows());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void connection_base::set_default_isolation_level(isolation_level level)
|
|
||||||
{
|
{
|
||||||
std::string level_str = "read uncommmitted";
|
std::string level_str = "read uncommmitted";
|
||||||
switch (level)
|
switch (level)
|
||||||
@ -494,7 +447,7 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! get the currently set default transaction isolation level
|
//! get the currently set default transaction isolation level
|
||||||
inline isolation_level connection_base::get_default_isolation_level()
|
isolation_level get_default_isolation_level()
|
||||||
{
|
{
|
||||||
auto res = execute("SHOW default_transaction_isolation;");
|
auto res = execute("SHOW default_transaction_isolation;");
|
||||||
auto status = res->result.status();
|
auto status = res->result.status();
|
||||||
@ -503,7 +456,7 @@ namespace sqlpp
|
|||||||
throw sqlpp::exception("PostgreSQL error: could not read default_transaction_isolation");
|
throw sqlpp::exception("PostgreSQL error: could not read default_transaction_isolation");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto in = res->result.getStringValue(0, 0);
|
auto in = res->result.get_string_value(0, 0);
|
||||||
if (in == "read committed")
|
if (in == "read committed")
|
||||||
{
|
{
|
||||||
return isolation_level::read_committed;
|
return isolation_level::read_committed;
|
||||||
@ -523,22 +476,29 @@ namespace sqlpp
|
|||||||
return isolation_level::undefined;
|
return isolation_level::undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Fix escaping.
|
//! create savepoint
|
||||||
inline std::string connection_base::escape(const std::string& s) const
|
void savepoint(const std::string& name)
|
||||||
{
|
{
|
||||||
validate_connection_handle();
|
/// NOTE prevent from sql injection?
|
||||||
// Escape strings
|
execute("SAVEPOINT " + name);
|
||||||
std::string result;
|
}
|
||||||
result.resize((s.size() * 2) + 1);
|
|
||||||
|
|
||||||
int err;
|
//! ROLLBACK TO SAVEPOINT
|
||||||
size_t length = PQescapeStringConn(native_handle(), &result[0], s.c_str(), s.size(), &err);
|
void rollback_to_savepoint(const std::string& name)
|
||||||
result.resize(length);
|
{
|
||||||
return result;
|
/// NOTE prevent from sql injection?
|
||||||
|
execute("ROLLBACK TO SAVEPOINT " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! release_savepoint
|
||||||
|
void release_savepoint(const std::string& name)
|
||||||
|
{
|
||||||
|
/// NOTE prevent from sql injection?
|
||||||
|
execute("RELEASE SAVEPOINT " + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! start transaction
|
//! start transaction
|
||||||
inline void connection_base::start_transaction(isolation_level level)
|
void start_transaction(isolation_level level = isolation_level::undefined)
|
||||||
{
|
{
|
||||||
if (_transaction_active)
|
if (_transaction_active)
|
||||||
{
|
{
|
||||||
@ -575,29 +535,8 @@ namespace sqlpp
|
|||||||
_transaction_active = true;
|
_transaction_active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! create savepoint
|
|
||||||
inline void connection_base::savepoint(const std::string& name)
|
|
||||||
{
|
|
||||||
/// NOTE prevent from sql injection?
|
|
||||||
execute("SAVEPOINT " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! ROLLBACK TO SAVEPOINT
|
|
||||||
inline void connection_base::rollback_to_savepoint(const std::string& name)
|
|
||||||
{
|
|
||||||
/// NOTE prevent from sql injection?
|
|
||||||
execute("ROLLBACK TO SAVEPOINT " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! release_savepoint
|
|
||||||
inline void connection_base::release_savepoint(const std::string& name)
|
|
||||||
{
|
|
||||||
/// NOTE prevent from sql injection?
|
|
||||||
execute("RELEASE SAVEPOINT " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! commit transaction (or throw transaction if transaction has finished already)
|
//! commit transaction (or throw transaction if transaction has finished already)
|
||||||
inline void connection_base::commit_transaction()
|
void commit_transaction()
|
||||||
{
|
{
|
||||||
if (!_transaction_active)
|
if (!_transaction_active)
|
||||||
{
|
{
|
||||||
@ -609,7 +548,7 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! rollback transaction
|
//! rollback transaction
|
||||||
inline void connection_base::rollback_transaction(bool report)
|
void rollback_transaction(bool report)
|
||||||
{
|
{
|
||||||
if (!_transaction_active)
|
if (!_transaction_active)
|
||||||
{
|
{
|
||||||
@ -625,12 +564,13 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! report rollback failure
|
//! report rollback failure
|
||||||
inline void connection_base::report_rollback_failure(const std::string& message) noexcept
|
void report_rollback_failure(const std::string& message) noexcept
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL error: " << message << std::endl;
|
std::cerr << "PostgreSQL error: " << message << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint64_t connection_base::last_insert_id(const std::string& table, const std::string& fieldname)
|
//! get the last inserted id for a certain table
|
||||||
|
uint64_t last_insert_id(const std::string& table, const std::string& fieldname)
|
||||||
{
|
{
|
||||||
std::string sql = "SELECT currval('" + table + "_" + fieldname + "_seq')";
|
std::string sql = "SELECT currval('" + table + "_" + fieldname + "_seq')";
|
||||||
PGresult* res = PQexec(native_handle(), sql.c_str());
|
PGresult* res = PQexec(native_handle(), sql.c_str());
|
||||||
@ -647,11 +587,22 @@ namespace sqlpp
|
|||||||
return std::stoul(in);
|
return std::stoul(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ::PGconn* connection_base::native_handle() const
|
::PGconn* native_handle() const
|
||||||
{
|
{
|
||||||
return _handle->native_handle();
|
return _handle->native_handle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
_handle_ptr_t _handle;
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
connection_base() = default;
|
||||||
|
connection_base(_handle_ptr_t&& handle) : _handle{std::move(handle)}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Method definition moved outside of class because it needs connection_base
|
||||||
inline std::string context_t::escape(const std::string& arg) const
|
inline std::string context_t::escape(const std::string& arg) const
|
||||||
{
|
{
|
||||||
return _db.escape(arg);
|
return _db.escape(arg);
|
||||||
|
@ -52,11 +52,6 @@ namespace sqlpp
|
|||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
inline void handle_cleanup(PGconn* postgres)
|
|
||||||
{
|
|
||||||
PQfinish(postgres);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DLL_LOCAL connection_handle
|
struct DLL_LOCAL connection_handle
|
||||||
{
|
{
|
||||||
std::shared_ptr<const connection_config> config;
|
std::shared_ptr<const connection_config> config;
|
||||||
@ -76,7 +71,7 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
inline connection_handle::connection_handle(const std::shared_ptr<const connection_config>& conf)
|
inline connection_handle::connection_handle(const std::shared_ptr<const connection_config>& conf)
|
||||||
: config(conf), postgres{nullptr, handle_cleanup}
|
: config(conf), postgres{nullptr, PQfinish}
|
||||||
{
|
{
|
||||||
#ifdef SQLPP_DYNAMIC_LOADING
|
#ifdef SQLPP_DYNAMIC_LOADING
|
||||||
init_pg("");
|
init_pg("");
|
||||||
|
@ -54,25 +54,45 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
struct DLL_PUBLIC statement_handle_t
|
struct DLL_PUBLIC statement_handle_t
|
||||||
{
|
{
|
||||||
detail::connection_handle& connection;
|
connection_handle& connection;
|
||||||
Result result;
|
Result result;
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int totalCount = 0;
|
int total_count = 0;
|
||||||
int fields = 0;
|
int fields = 0;
|
||||||
|
|
||||||
// ctor
|
// ctor
|
||||||
statement_handle_t(detail::connection_handle& _connection);
|
statement_handle_t(connection_handle& _connection) : connection(_connection)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
statement_handle_t(const statement_handle_t&) = delete;
|
statement_handle_t(const statement_handle_t&) = delete;
|
||||||
statement_handle_t(statement_handle_t&&) = delete;
|
statement_handle_t(statement_handle_t&&) = delete;
|
||||||
statement_handle_t& operator=(const statement_handle_t&) = delete;
|
statement_handle_t& operator=(const statement_handle_t&) = delete;
|
||||||
statement_handle_t& operator=(statement_handle_t&&) = delete;
|
statement_handle_t& operator=(statement_handle_t&&) = delete;
|
||||||
|
|
||||||
virtual ~statement_handle_t();
|
virtual ~statement_handle_t()
|
||||||
bool operator!() const;
|
{
|
||||||
void clearResult();
|
clear_result();
|
||||||
|
}
|
||||||
|
|
||||||
bool debug() const;
|
bool operator!() const
|
||||||
|
{
|
||||||
|
return !valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_result()
|
||||||
|
{
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
result.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool debug() const
|
||||||
|
{
|
||||||
|
return connection.config->debug;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct prepared_statement_handle_t : public statement_handle_t
|
struct prepared_statement_handle_t : public statement_handle_t
|
||||||
@ -82,67 +102,23 @@ namespace sqlpp
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// Store prepared statement arguments
|
// Store prepared statement arguments
|
||||||
std::vector<bool> nullValues;
|
std::vector<bool> null_values;
|
||||||
std::vector<std::string> paramValues;
|
std::vector<std::string> param_values;
|
||||||
|
|
||||||
// ctor
|
// ctor
|
||||||
prepared_statement_handle_t(detail::connection_handle& _connection, std::string stmt, const size_t& paramCount);
|
prepared_statement_handle_t(connection_handle& _connection, const std::string& stmt, const size_t& param_count)
|
||||||
prepared_statement_handle_t(const prepared_statement_handle_t&) = delete;
|
: statement_handle_t(_connection), null_values(param_count), param_values(param_count)
|
||||||
prepared_statement_handle_t(prepared_statement_handle_t&&) = delete;
|
|
||||||
prepared_statement_handle_t& operator=(const prepared_statement_handle_t&) = delete;
|
|
||||||
prepared_statement_handle_t& operator=(prepared_statement_handle_t&&) = delete;
|
|
||||||
|
|
||||||
virtual ~prepared_statement_handle_t();
|
|
||||||
|
|
||||||
void execute();
|
|
||||||
|
|
||||||
std::string name() const
|
|
||||||
{
|
|
||||||
return _name;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void generate_name();
|
|
||||||
void prepare(std::string stmt);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline statement_handle_t::statement_handle_t(connection_handle& _connection) : connection(_connection)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
inline statement_handle_t::~statement_handle_t()
|
|
||||||
{
|
|
||||||
clearResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool statement_handle_t::operator!() const
|
|
||||||
{
|
|
||||||
return !valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void statement_handle_t::clearResult()
|
|
||||||
{
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
result.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool statement_handle_t::debug() const
|
|
||||||
{
|
|
||||||
return connection.config->debug;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline prepared_statement_handle_t::prepared_statement_handle_t(connection_handle& _connection,
|
|
||||||
std::string stmt,
|
|
||||||
const size_t& paramCount)
|
|
||||||
: statement_handle_t(_connection), nullValues(paramCount), paramValues(paramCount)
|
|
||||||
{
|
{
|
||||||
generate_name();
|
generate_name();
|
||||||
prepare(std::move(stmt));
|
prepare(std::move(stmt));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline prepared_statement_handle_t::~prepared_statement_handle_t()
|
prepared_statement_handle_t(const prepared_statement_handle_t&) = delete;
|
||||||
|
prepared_statement_handle_t(prepared_statement_handle_t&&) = delete;
|
||||||
|
prepared_statement_handle_t& operator=(const prepared_statement_handle_t&) = delete;
|
||||||
|
prepared_statement_handle_t& operator=(prepared_statement_handle_t&&) = delete;
|
||||||
|
|
||||||
|
virtual ~prepared_statement_handle_t()
|
||||||
{
|
{
|
||||||
if (valid && !_name.empty())
|
if (valid && !_name.empty())
|
||||||
{
|
{
|
||||||
@ -150,25 +126,31 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void prepared_statement_handle_t::execute()
|
void execute()
|
||||||
{
|
{
|
||||||
const size_t size = paramValues.size();
|
const size_t size = param_values.size();
|
||||||
|
|
||||||
std::vector<const char*> values;
|
std::vector<const char*> values;
|
||||||
for (size_t i = 0u; i < size; i++)
|
for (size_t i = 0u; i < size; i++)
|
||||||
values.push_back(nullValues[i] ? nullptr : const_cast<char*>(paramValues[i].c_str()));
|
values.push_back(null_values[i] ? nullptr : const_cast<char*>(param_values[i].c_str()));
|
||||||
|
|
||||||
// Execute prepared statement with the parameters.
|
// Execute prepared statement with the parameters.
|
||||||
clearResult();
|
clear_result();
|
||||||
valid = false;
|
valid = false;
|
||||||
count = 0;
|
count = 0;
|
||||||
totalCount = 0;
|
total_count = 0;
|
||||||
result = PQexecPrepared(connection.native_handle(), _name.data(), static_cast<int>(size), values.data(), nullptr, nullptr, 0);
|
result = PQexecPrepared(connection.native_handle(), _name.data(), static_cast<int>(size), values.data(), nullptr, nullptr, 0);
|
||||||
/// @todo validate result? is it really valid
|
/// @todo validate result? is it really valid
|
||||||
valid = true;
|
valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void prepared_statement_handle_t::generate_name()
|
std::string name() const
|
||||||
|
{
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void generate_name()
|
||||||
{
|
{
|
||||||
// Generate a random name for the prepared statement
|
// Generate a random name for the prepared statement
|
||||||
while (connection.prepared_statement_names.find(_name) != connection.prepared_statement_names.end())
|
while (connection.prepared_statement_names.find(_name) != connection.prepared_statement_names.end())
|
||||||
@ -184,12 +166,13 @@ namespace sqlpp
|
|||||||
connection.prepared_statement_names.insert(_name);
|
connection.prepared_statement_names.insert(_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void prepared_statement_handle_t::prepare(std::string stmt)
|
void prepare(const std::string& stmt)
|
||||||
{
|
{
|
||||||
// Create the prepared statement
|
// Create the prepared statement
|
||||||
result = PQprepare(connection.native_handle(), _name.c_str(), stmt.c_str(), 0, nullptr);
|
result = PQprepare(connection.native_handle(), _name.c_str(), stmt.c_str(), 0, nullptr);
|
||||||
valid = true;
|
valid = true;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,18 @@ namespace sqlpp
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
prepared_statement_t() = default;
|
prepared_statement_t() = default;
|
||||||
prepared_statement_t(std::shared_ptr<detail::prepared_statement_handle_t>&& handle);
|
|
||||||
|
// ctor
|
||||||
|
prepared_statement_t(std::shared_ptr<detail::prepared_statement_handle_t>&& handle)
|
||||||
|
: _handle{handle}
|
||||||
|
{
|
||||||
|
if (_handle && _handle->debug())
|
||||||
|
{
|
||||||
|
std::cerr << "PostgreSQL debug: constructing prepared_statement, using handle at: " << _handle.get()
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
prepared_statement_t(const prepared_statement_t&) = delete;
|
prepared_statement_t(const prepared_statement_t&) = delete;
|
||||||
prepared_statement_t(prepared_statement_t&&) = default;
|
prepared_statement_t(prepared_statement_t&&) = default;
|
||||||
prepared_statement_t& operator=(const prepared_statement_t&) = delete;
|
prepared_statement_t& operator=(const prepared_statement_t&) = delete;
|
||||||
@ -72,28 +83,7 @@ namespace sqlpp
|
|||||||
return (this->_handle == rhs._handle);
|
return (this->_handle == rhs._handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_boolean_parameter(size_t index, const signed char* value, bool is_null);
|
void _bind_boolean_parameter(size_t index, const signed char* value, bool is_null)
|
||||||
void _bind_floating_point_parameter(size_t index, const double* value, bool is_null);
|
|
||||||
void _bind_integral_parameter(size_t index, const int64_t* 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_time_of_day_parameter(size_t index, const ::std::chrono::microseconds* value, bool is_null);
|
|
||||||
void _bind_date_time_parameter(size_t index, const ::sqlpp::chrono::microsecond_point* value, bool is_null);
|
|
||||||
void _bind_blob_parameter(size_t index, const std::vector<unsigned char>* value, bool is_null);
|
|
||||||
};
|
|
||||||
|
|
||||||
// ctor
|
|
||||||
inline prepared_statement_t::prepared_statement_t(std::shared_ptr<detail::prepared_statement_handle_t>&& handle)
|
|
||||||
: _handle{handle}
|
|
||||||
{
|
|
||||||
if (_handle && _handle->debug())
|
|
||||||
{
|
|
||||||
std::cerr << "PostgreSQL debug: constructing prepared_statement, using handle at: " << _handle.get()
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void prepared_statement_t::_bind_boolean_parameter(size_t index, const signed char* value, bool is_null)
|
|
||||||
{
|
{
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
@ -101,21 +91,21 @@ namespace sqlpp
|
|||||||
<< " at index: " << index << ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
<< " at index: " << index << ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
_handle->nullValues[index] = is_null;
|
_handle->null_values[index] = is_null;
|
||||||
if (!is_null)
|
if (!is_null)
|
||||||
{
|
{
|
||||||
if (*value)
|
if (*value)
|
||||||
{
|
{
|
||||||
_handle->paramValues[index] = "TRUE";
|
_handle->param_values[index] = "TRUE";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_handle->paramValues[index] = "FALSE";
|
_handle->param_values[index] = "FALSE";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void prepared_statement_t::_bind_floating_point_parameter(size_t index, const double* value, bool is_null)
|
void _bind_floating_point_parameter(size_t index, const double* value, bool is_null)
|
||||||
{
|
{
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
@ -123,16 +113,16 @@ namespace sqlpp
|
|||||||
<< ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
<< ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
_handle->nullValues[index] = is_null;
|
_handle->null_values[index] = is_null;
|
||||||
if (!is_null)
|
if (!is_null)
|
||||||
{
|
{
|
||||||
sqlpp::detail::float_safe_ostringstream out;
|
sqlpp::detail::float_safe_ostringstream out;
|
||||||
out << *value;
|
out << *value;
|
||||||
_handle->paramValues[index] = out.str();
|
_handle->param_values[index] = out.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void prepared_statement_t::_bind_integral_parameter(size_t index, const int64_t* value, bool is_null)
|
void _bind_integral_parameter(size_t index, const int64_t* value, bool is_null)
|
||||||
{
|
{
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
@ -141,14 +131,14 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Assign values
|
// Assign values
|
||||||
_handle->nullValues[index] = is_null;
|
_handle->null_values[index] = is_null;
|
||||||
if (!is_null)
|
if (!is_null)
|
||||||
{
|
{
|
||||||
_handle->paramValues[index] = std::to_string(*value);
|
_handle->param_values[index] = std::to_string(*value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void prepared_statement_t::_bind_text_parameter(size_t index, const std::string* value, bool is_null)
|
void _bind_text_parameter(size_t index, const std::string* value, bool is_null)
|
||||||
{
|
{
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
@ -157,43 +147,43 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Assign values
|
// Assign values
|
||||||
_handle->nullValues[index] = is_null;
|
_handle->null_values[index] = is_null;
|
||||||
if (!is_null)
|
if (!is_null)
|
||||||
{
|
{
|
||||||
_handle->paramValues[index] = *value;
|
_handle->param_values[index] = *value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void prepared_statement_t::_bind_date_parameter(size_t index, const ::sqlpp::chrono::day_point* value, bool is_null)
|
void _bind_date_parameter(size_t index, const ::sqlpp::chrono::day_point* value, bool is_null)
|
||||||
{
|
{
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding date parameter at index "
|
std::cerr << "PostgreSQL debug: binding date parameter at index "
|
||||||
<< index << ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
<< index << ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||||
}
|
}
|
||||||
_handle->nullValues[index] = is_null;
|
_handle->null_values[index] = is_null;
|
||||||
if (not is_null)
|
if (not is_null)
|
||||||
{
|
{
|
||||||
const auto ymd = ::date::year_month_day{*value};
|
const auto ymd = ::date::year_month_day{*value};
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os << ymd;
|
os << ymd;
|
||||||
_handle->paramValues[index] = os.str();
|
_handle->param_values[index] = os.str();
|
||||||
|
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding date parameter string: " << _handle->paramValues[index] << std::endl;
|
std::cerr << "PostgreSQL debug: binding date parameter string: " << _handle->param_values[index] << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void prepared_statement_t::_bind_time_of_day_parameter(size_t index, const ::std::chrono::microseconds* value, bool is_null)
|
void _bind_time_of_day_parameter(size_t index, const ::std::chrono::microseconds* value, bool is_null)
|
||||||
{
|
{
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding time parameter at index "
|
std::cerr << "PostgreSQL debug: binding time parameter at index "
|
||||||
<< index << ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
<< index << ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||||
}
|
}
|
||||||
_handle->nullValues[index] = is_null;
|
_handle->null_values[index] = is_null;
|
||||||
if (not is_null)
|
if (not is_null)
|
||||||
{
|
{
|
||||||
const auto time = ::date::make_time(*value) ;
|
const auto time = ::date::make_time(*value) ;
|
||||||
@ -201,22 +191,22 @@ namespace sqlpp
|
|||||||
// Timezone handling - always treat the local value as UTC.
|
// Timezone handling - always treat the local value as UTC.
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os << time << "+00";
|
os << time << "+00";
|
||||||
_handle->paramValues[index] = os.str();
|
_handle->param_values[index] = os.str();
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding time parameter string: " << _handle->paramValues[index] << std::endl;
|
std::cerr << "PostgreSQL debug: binding time parameter string: " << _handle->param_values[index] << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void prepared_statement_t::_bind_date_time_parameter(size_t index, const ::sqlpp::chrono::microsecond_point* value, bool is_null)
|
void _bind_date_time_parameter(size_t index, const ::sqlpp::chrono::microsecond_point* value, bool is_null)
|
||||||
{
|
{
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding date_time parameter at index "
|
std::cerr << "PostgreSQL debug: binding date_time parameter at index "
|
||||||
<< index << ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
<< index << ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||||
}
|
}
|
||||||
_handle->nullValues[index] = is_null;
|
_handle->null_values[index] = is_null;
|
||||||
if (not is_null)
|
if (not is_null)
|
||||||
{
|
{
|
||||||
const auto dp = ::sqlpp::chrono::floor<::date::days>(*value);
|
const auto dp = ::sqlpp::chrono::floor<::date::days>(*value);
|
||||||
@ -226,40 +216,41 @@ namespace sqlpp
|
|||||||
// Timezone handling - always treat the local value as UTC.
|
// Timezone handling - always treat the local value as UTC.
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os << ymd << ' ' << time << "+00";
|
os << ymd << ' ' << time << "+00";
|
||||||
_handle->paramValues[index] = os.str();
|
_handle->param_values[index] = os.str();
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding date_time parameter string: " << _handle->paramValues[index] << std::endl;
|
std::cerr << "PostgreSQL debug: binding date_time parameter string: " << _handle->param_values[index] << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void prepared_statement_t::_bind_blob_parameter(size_t index, const std::vector<unsigned char>* value, bool is_null)
|
void _bind_blob_parameter(size_t index, const std::vector<unsigned char>* value, bool is_null)
|
||||||
{
|
{
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding blob parameter at index "
|
std::cerr << "PostgreSQL debug: binding blob parameter at index "
|
||||||
<< index << ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
<< index << ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||||
}
|
}
|
||||||
_handle->nullValues[index] = is_null;
|
_handle->null_values[index] = is_null;
|
||||||
if (not is_null)
|
if (not is_null)
|
||||||
{
|
{
|
||||||
constexpr char hexChars[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
constexpr char hex_chars[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||||
auto param = std::string(value->size() * 2 + 2, '\0');
|
auto param = std::string(value->size() * 2 + 2, '\0');
|
||||||
param[0] = '\\';
|
param[0] = '\\';
|
||||||
param[1] = 'x';
|
param[1] = 'x';
|
||||||
auto i = size_t{1};
|
auto i = size_t{1};
|
||||||
for (const auto c : *value)
|
for (const auto c : *value)
|
||||||
{
|
{
|
||||||
param[++i] = hexChars[c >> 4];
|
param[++i] = hex_chars[c >> 4];
|
||||||
param[++i] = hexChars[c & 0x0F];
|
param[++i] = hex_chars[c & 0x0F];
|
||||||
}
|
}
|
||||||
_handle->paramValues[index] = std::move(param);
|
_handle->param_values[index] = std::move(param);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding blob parameter string (up to 100 chars): " << _handle->paramValues[index].substr(0, 100) << std::endl;
|
std::cerr << "PostgreSQL debug: binding blob parameter string (up to 100 chars): " << _handle->param_values[index].substr(0, 100) << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,26 +53,71 @@ namespace sqlpp
|
|||||||
class DLL_PUBLIC Result
|
class DLL_PUBLIC Result
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Result();
|
Result() : m_result(nullptr)
|
||||||
~Result();
|
|
||||||
|
|
||||||
ExecStatusType status();
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
int affected_rows();
|
|
||||||
int records_size() const;
|
|
||||||
int field_count() const;
|
|
||||||
int length(int record, int field) const;
|
|
||||||
bool isNull(int record, int field) const;
|
|
||||||
void operator=(PGresult* res);
|
|
||||||
operator bool() const;
|
|
||||||
|
|
||||||
inline int64_t getInt64Value(int record, int field) const
|
|
||||||
{
|
{
|
||||||
checkIndex(record, field);
|
}
|
||||||
|
|
||||||
|
~Result()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
ExecStatusType status()
|
||||||
|
{
|
||||||
|
return PQresultStatus(m_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
if (m_result)
|
||||||
|
PQclear(m_result);
|
||||||
|
m_result = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int affected_rows()
|
||||||
|
{
|
||||||
|
const char* const rows_str = PQcmdTuples(m_result);
|
||||||
|
return rows_str[0] ? std::stoi(std::string(rows_str)) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int records_size() const
|
||||||
|
{
|
||||||
|
return m_result ? PQntuples(m_result) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int field_count() const
|
||||||
|
{
|
||||||
|
return m_result ? PQnfields(m_result) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length(int record, int field) const
|
||||||
|
{
|
||||||
|
/// check index?
|
||||||
|
return PQgetlength(m_result, record, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_null(int record, int field) const
|
||||||
|
{
|
||||||
|
/// check index?
|
||||||
|
return PQgetisnull(m_result, record, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator=(PGresult* res)
|
||||||
|
{
|
||||||
|
m_result = res;
|
||||||
|
check_status();
|
||||||
|
}
|
||||||
|
|
||||||
|
operator bool() const
|
||||||
|
{
|
||||||
|
return m_result != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t get_int64_value(int record, int field) const
|
||||||
|
{
|
||||||
|
check_index(record, field);
|
||||||
auto t = int64_t{};
|
auto t = int64_t{};
|
||||||
const auto txt = std::string(getPqValue(m_result, record, field));
|
const auto txt = std::string(get_pq_value(m_result, record, field));
|
||||||
if(txt != "")
|
if(txt != "")
|
||||||
{
|
{
|
||||||
t = std::stoll(txt);
|
t = std::stoll(txt);
|
||||||
@ -81,11 +126,11 @@ namespace sqlpp
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint64_t getUInt64Value(int record, int field) const
|
uint64_t get_uint64_value(int record, int field) const
|
||||||
{
|
{
|
||||||
checkIndex(record, field);
|
check_index(record, field);
|
||||||
auto t = uint64_t{};
|
auto t = uint64_t{};
|
||||||
const auto txt = std::string(getPqValue(m_result, record, field));
|
const auto txt = std::string(get_pq_value(m_result, record, field));
|
||||||
if(txt != "")
|
if(txt != "")
|
||||||
{
|
{
|
||||||
t = std::stoull(txt);
|
t = std::stoull(txt);
|
||||||
@ -94,11 +139,11 @@ namespace sqlpp
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double getDoubleValue(int record, int field) const
|
double get_double_value(int record, int field) const
|
||||||
{
|
{
|
||||||
checkIndex(record, field);
|
check_index(record, field);
|
||||||
auto t = double{};
|
auto t = double{};
|
||||||
auto txt = std::string(getPqValue(m_result, record, field));
|
auto txt = std::string(get_pq_value(m_result, record, field));
|
||||||
if(txt != "")
|
if(txt != "")
|
||||||
{
|
{
|
||||||
t = std::stod(txt);
|
t = std::stod(txt);
|
||||||
@ -107,25 +152,25 @@ namespace sqlpp
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char* getCharPtrValue(int record, int field) const
|
const char* get_char_ptr_value(int record, int field) const
|
||||||
{
|
{
|
||||||
return const_cast<const char*>(getPqValue(m_result, record, field));
|
return const_cast<const char*>(get_pq_value(m_result, record, field));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string getStringValue(int record, int field) const
|
std::string get_string_value(int record, int field) const
|
||||||
{
|
{
|
||||||
return {getCharPtrValue(record, field)};
|
return {get_char_ptr_value(record, field)};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const uint8_t* getBlobValue(int record, int field) const
|
const uint8_t* get_blob_value(int record, int field) const
|
||||||
{
|
{
|
||||||
return reinterpret_cast<const uint8_t*>(getPqValue(m_result, record, field));
|
return reinterpret_cast<const uint8_t*>(get_pq_value(m_result, record, field));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool getBoolValue(int record, int field) const
|
bool get_bool_value(int record, int field) const
|
||||||
{
|
{
|
||||||
checkIndex(record, field);
|
check_index(record, field);
|
||||||
auto val = getPqValue(m_result, record, field);
|
auto val = get_pq_value(m_result, record, field);
|
||||||
if (*val == 't')
|
if (*val == 't')
|
||||||
return true;
|
return true;
|
||||||
else if (*val == 'f')
|
else if (*val == 'f')
|
||||||
@ -144,51 +189,14 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CheckStatus() const;
|
void check_status() const
|
||||||
[[noreturn]] void ThrowSQLError(const std::string& Err, const std::string& Query) const;
|
|
||||||
std::string StatusError() const;
|
|
||||||
int errorPosition() const noexcept;
|
|
||||||
bool hasError();
|
|
||||||
void checkIndex(int record, int field) const noexcept(false);
|
|
||||||
|
|
||||||
// move PQgetvalue to implementation so we don't depend on the libpq in the
|
|
||||||
// public interface
|
|
||||||
const char* getPqValue(PGresult* result, int record, int field) const;
|
|
||||||
|
|
||||||
PGresult* m_result;
|
|
||||||
std::string m_query;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
inline Result::Result() : m_result(nullptr)
|
|
||||||
{
|
{
|
||||||
|
const std::string err = status_error();
|
||||||
|
if (!err.empty())
|
||||||
|
throw_sql_error(err, query());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Result::checkIndex(int record, int field) const noexcept(false)
|
[[noreturn]] void throw_sql_error(const std::string& err, const std::string& query) const
|
||||||
{
|
|
||||||
if (record > records_size() || field > field_count())
|
|
||||||
throw std::out_of_range("PostgreSQL error: index out of range");
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Result::operator=(PGresult* res)
|
|
||||||
{
|
|
||||||
m_result = res;
|
|
||||||
CheckStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Result::CheckStatus() const
|
|
||||||
{
|
|
||||||
const std::string Err = StatusError();
|
|
||||||
if (!Err.empty())
|
|
||||||
ThrowSQLError(Err, query());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char* Result::getPqValue(PGresult* result, int record, int field) const
|
|
||||||
{
|
|
||||||
return const_cast<const char*>(PQgetvalue(result, record, field));
|
|
||||||
}
|
|
||||||
|
|
||||||
[[noreturn]] inline void Result::ThrowSQLError(const std::string& Err, const std::string& Query) const
|
|
||||||
{
|
{
|
||||||
// Try to establish more precise error type, and throw corresponding exception
|
// Try to establish more precise error type, and throw corresponding exception
|
||||||
const char* const code = PQresultErrorField(m_result, PG_DIAG_SQLSTATE);
|
const char* const code = PQresultErrorField(m_result, PG_DIAG_SQLSTATE);
|
||||||
@ -199,39 +207,39 @@ namespace sqlpp
|
|||||||
switch (code[1])
|
switch (code[1])
|
||||||
{
|
{
|
||||||
case '8':
|
case '8':
|
||||||
throw broken_connection(Err);
|
throw broken_connection(err);
|
||||||
case 'A':
|
case 'A':
|
||||||
throw feature_not_supported(Err, Query);
|
throw feature_not_supported(err, query);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '2':
|
case '2':
|
||||||
switch (code[1])
|
switch (code[1])
|
||||||
{
|
{
|
||||||
case '2':
|
case '2':
|
||||||
throw data_exception(Err, Query);
|
throw data_exception(err, query);
|
||||||
case '3':
|
case '3':
|
||||||
if (strcmp(code, "23001") == 0)
|
if (strcmp(code, "23001") == 0)
|
||||||
throw restrict_violation(Err, Query);
|
throw restrict_violation(err, query);
|
||||||
if (strcmp(code, "23502") == 0)
|
if (strcmp(code, "23502") == 0)
|
||||||
throw not_null_violation(Err, Query);
|
throw not_null_violation(err, query);
|
||||||
if (strcmp(code, "23503") == 0)
|
if (strcmp(code, "23503") == 0)
|
||||||
throw foreign_key_violation(Err, Query);
|
throw foreign_key_violation(err, query);
|
||||||
if (strcmp(code, "23505") == 0)
|
if (strcmp(code, "23505") == 0)
|
||||||
throw unique_violation(Err, Query);
|
throw unique_violation(err, query);
|
||||||
if (strcmp(code, "23514") == 0)
|
if (strcmp(code, "23514") == 0)
|
||||||
throw check_violation(Err, Query);
|
throw check_violation(err, query);
|
||||||
throw integrity_constraint_violation(Err, Query);
|
throw integrity_constraint_violation(err, query);
|
||||||
case '4':
|
case '4':
|
||||||
throw invalid_cursor_state(Err, Query);
|
throw invalid_cursor_state(err, query);
|
||||||
case '6':
|
case '6':
|
||||||
throw invalid_sql_statement_name(Err, Query);
|
throw invalid_sql_statement_name(err, query);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '3':
|
case '3':
|
||||||
switch (code[1])
|
switch (code[1])
|
||||||
{
|
{
|
||||||
case '4':
|
case '4':
|
||||||
throw invalid_cursor_name(Err, Query);
|
throw invalid_cursor_name(err, query);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '4':
|
case '4':
|
||||||
@ -239,15 +247,15 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
case '2':
|
case '2':
|
||||||
if (strcmp(code, "42501") == 0)
|
if (strcmp(code, "42501") == 0)
|
||||||
throw insufficient_privilege(Err, Query);
|
throw insufficient_privilege(err, query);
|
||||||
if (strcmp(code, "42601") == 0)
|
if (strcmp(code, "42601") == 0)
|
||||||
throw syntax_error(Err, Query, errorPosition());
|
throw syntax_error(err, query, error_position());
|
||||||
if (strcmp(code, "42703") == 0)
|
if (strcmp(code, "42703") == 0)
|
||||||
throw undefined_column(Err, Query);
|
throw undefined_column(err, query);
|
||||||
if (strcmp(code, "42883") == 0)
|
if (strcmp(code, "42883") == 0)
|
||||||
throw undefined_function(Err, Query);
|
throw undefined_function(err, query);
|
||||||
if (strcmp(code, "42P01") == 0)
|
if (strcmp(code, "42P01") == 0)
|
||||||
throw undefined_table(Err, Query);
|
throw undefined_table(err, query);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '5':
|
case '5':
|
||||||
@ -255,36 +263,36 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
case '3':
|
case '3':
|
||||||
if (strcmp(code, "53100") == 0)
|
if (strcmp(code, "53100") == 0)
|
||||||
throw disk_full(Err, Query);
|
throw disk_full(err, query);
|
||||||
if (strcmp(code, "53200") == 0)
|
if (strcmp(code, "53200") == 0)
|
||||||
throw out_of_memory(Err, Query);
|
throw out_of_memory(err, query);
|
||||||
if (strcmp(code, "53300") == 0)
|
if (strcmp(code, "53300") == 0)
|
||||||
throw too_many_connections(Err);
|
throw too_many_connections(err);
|
||||||
throw insufficient_resources(Err, Query);
|
throw insufficient_resources(err, query);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
if (strcmp(code, "P0001") == 0)
|
if (strcmp(code, "P0001") == 0)
|
||||||
throw plpgsql_raise(Err, Query);
|
throw plpgsql_raise(err, query);
|
||||||
if (strcmp(code, "P0002") == 0)
|
if (strcmp(code, "P0002") == 0)
|
||||||
throw plpgsql_no_data_found(Err, Query);
|
throw plpgsql_no_data_found(err, query);
|
||||||
if (strcmp(code, "P0003") == 0)
|
if (strcmp(code, "P0003") == 0)
|
||||||
throw plpgsql_too_many_rows(Err, Query);
|
throw plpgsql_too_many_rows(err, query);
|
||||||
throw plpgsql_error(Err, Query);
|
throw plpgsql_error(err, query);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw sql_user_error(Err, Query, code);
|
throw sql_user_error(err, query, code);
|
||||||
}
|
}
|
||||||
throw sql_error(Err, Query);
|
throw sql_error(err, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string Result::StatusError() const
|
std::string status_error() const
|
||||||
{
|
{
|
||||||
if (!m_result)
|
if (!m_result)
|
||||||
throw failure("No result set given");
|
throw failure("No result set given");
|
||||||
|
|
||||||
std::string Err;
|
std::string err;
|
||||||
|
|
||||||
switch (PQresultStatus(m_result))
|
switch (PQresultStatus(m_result))
|
||||||
{
|
{
|
||||||
@ -300,24 +308,24 @@ namespace sqlpp
|
|||||||
case PGRES_BAD_RESPONSE: // The server's response was not understood
|
case PGRES_BAD_RESPONSE: // The server's response was not understood
|
||||||
case PGRES_NONFATAL_ERROR:
|
case PGRES_NONFATAL_ERROR:
|
||||||
case PGRES_FATAL_ERROR:
|
case PGRES_FATAL_ERROR:
|
||||||
Err = PQresultErrorMessage(m_result);
|
err = PQresultErrorMessage(m_result);
|
||||||
break;
|
break;
|
||||||
#if PG_MAJORVERSION_NUM >= 13
|
#if PG_MAJORVERSION_NUM >= 13
|
||||||
case PGRES_COPY_BOTH:
|
case PGRES_COPY_BOTH:
|
||||||
case PGRES_SINGLE_TUPLE:
|
case PGRES_SINGLE_TUPLE:
|
||||||
#endif
|
#endif
|
||||||
#if PG_MAJORVERSION_NUM >= 14
|
#if PG_MAJORVERSION_NUM >= 14
|
||||||
case PGRES_PIPELINE_SYNC:
|
case PGRES_PIPELINE_SYNC:
|
||||||
case PGRES_PIPELINE_ABORTED:
|
case PGRES_PIPELINE_ABORTED:
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
throw sqlpp::exception("pqxx::result: Unrecognized response code " +
|
throw sqlpp::exception("pqxx::result: Unrecognized response code " +
|
||||||
std::to_string(PQresultStatus(m_result)));
|
std::to_string(PQresultStatus(m_result)));
|
||||||
}
|
}
|
||||||
return Err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Result::errorPosition() const noexcept
|
int error_position() const noexcept
|
||||||
{
|
{
|
||||||
int pos = -1;
|
int pos = -1;
|
||||||
if (m_result)
|
if (m_result)
|
||||||
@ -329,54 +337,21 @@ namespace sqlpp
|
|||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline sqlpp::postgresql::Result::operator bool() const
|
void check_index(int record, int field) const noexcept(false)
|
||||||
{
|
{
|
||||||
return m_result != 0;
|
if (record > records_size() || field > field_count())
|
||||||
|
throw std::out_of_range("PostgreSQL error: index out of range");
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Result::clear()
|
// move PQgetvalue to implementation so we don't depend on the libpq in the
|
||||||
|
// public interface
|
||||||
|
const char* get_pq_value(PGresult* result, int record, int field) const
|
||||||
{
|
{
|
||||||
if (m_result)
|
return const_cast<const char*>(PQgetvalue(result, record, field));
|
||||||
PQclear(m_result);
|
|
||||||
m_result = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Result::affected_rows()
|
PGresult* m_result;
|
||||||
{
|
std::string m_query;
|
||||||
const char* const RowsStr = PQcmdTuples(m_result);
|
};
|
||||||
return RowsStr[0] ? std::stoi(std::string(RowsStr)) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int Result::records_size() const
|
|
||||||
{
|
|
||||||
return m_result ? PQntuples(m_result) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int Result::field_count() const
|
|
||||||
{
|
|
||||||
return m_result ? PQnfields(m_result) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool Result::isNull(int record, int field) const
|
|
||||||
{
|
|
||||||
/// check index?
|
|
||||||
return PQgetisnull(m_result, record, field);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int Result::length(int record, int field) const
|
|
||||||
{
|
|
||||||
/// check index?
|
|
||||||
return PQgetlength(m_result, record, field);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Result::~Result()
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ExecStatusType Result::status()
|
|
||||||
{
|
|
||||||
return PQresultStatus(m_result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,11 +44,11 @@ namespace sqlpp
|
|||||||
|
|
||||||
inline postgresql::context_t& serialize(const blob_operand& t, postgresql::context_t& context)
|
inline postgresql::context_t& serialize(const blob_operand& t, postgresql::context_t& context)
|
||||||
{
|
{
|
||||||
constexpr char hexChars[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
constexpr char hex_chars[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||||
context << "'\\x";
|
context << "'\\x";
|
||||||
for (const auto c : t._t)
|
for (const auto c : t._t)
|
||||||
{
|
{
|
||||||
context << hexChars[c >> 4] << hexChars[c & 0x0F];
|
context << hex_chars[c >> 4] << hex_chars[c & 0x0F];
|
||||||
}
|
}
|
||||||
context << '\'';
|
context << '\'';
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user