mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Add support for TIME columns in postgresql
This commit is contained in:
parent
b2166c636b
commit
f7f2060c44
@ -104,6 +104,7 @@ namespace sqlpp
|
|||||||
void _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);
|
||||||
void _bind_date_result(size_t index, ::sqlpp::chrono::day_point* value, bool* is_null);
|
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_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);
|
void _bind_blob_result(size_t index, const uint8_t** value, size_t* len);
|
||||||
|
|
||||||
int size() const;
|
int size() const;
|
||||||
@ -401,6 +402,54 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// always returns local 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)
|
||||||
|
{
|
||||||
|
auto index = static_cast<int>(_index);
|
||||||
|
if (_handle->debug())
|
||||||
|
{
|
||||||
|
std::cerr << "PostgreSQL debug: binding time result at index: " << index << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
*is_null = _handle->result.isNull(_handle->count, index);
|
||||||
|
|
||||||
|
if (!(*is_null))
|
||||||
|
{
|
||||||
|
const auto time_string = _handle->result.getCharPtrValue(_handle->count, index);
|
||||||
|
|
||||||
|
if (_handle->debug())
|
||||||
|
{
|
||||||
|
std::cerr << "PostgreSQL debug: got time string: " << time_string << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (detail::check_time_digits(time_string))
|
||||||
|
{
|
||||||
|
*value += std::chrono::hours(std::atoi(time_string)) + std::chrono::minutes(std::atoi(time_string + 3)) +
|
||||||
|
std::chrono::seconds(std::atoi(time_string + 6));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::strlen(time_string) <= 9)
|
||||||
|
return;
|
||||||
|
auto us_string = time_string + 9; // hh:mm:ss.
|
||||||
|
int usec = 0;
|
||||||
|
for (size_t i = 0u; i < 6u; ++i)
|
||||||
|
{
|
||||||
|
if (std::isdigit(us_string[0]))
|
||||||
|
{
|
||||||
|
usec = 10 * usec + (us_string[0] - '0');
|
||||||
|
++us_string;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
usec *= 10;
|
||||||
|
}
|
||||||
|
*value += ::std::chrono::microseconds(usec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void bind_result_t::_bind_blob_result(size_t _index, const uint8_t** value, size_t* len)
|
inline void bind_result_t::_bind_blob_result(size_t _index, const uint8_t** value, size_t* len)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -78,6 +78,7 @@ namespace sqlpp
|
|||||||
void _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);
|
||||||
void _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);
|
||||||
void _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);
|
||||||
|
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_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);
|
void _bind_blob_parameter(size_t index, const std::vector<unsigned char>* value, bool is_null);
|
||||||
};
|
};
|
||||||
@ -187,6 +188,30 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void prepared_statement_t::_bind_time_of_day_parameter(size_t index, const ::std::chrono::microseconds* value, bool is_null)
|
||||||
|
{
|
||||||
|
if (_handle->debug())
|
||||||
|
{
|
||||||
|
std::cerr << "PostgreSQL debug: binding time parameter at index "
|
||||||
|
<< index << ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||||
|
}
|
||||||
|
_handle->nullValues[index] = is_null;
|
||||||
|
if (not is_null)
|
||||||
|
{
|
||||||
|
const auto time = ::date::make_time(*value) ;
|
||||||
|
|
||||||
|
// Timezone handling - always treat the value as UTC.
|
||||||
|
// It is assumed that the database timezone is set to UTC, too.
|
||||||
|
std::ostringstream os;
|
||||||
|
os << time;
|
||||||
|
_handle->paramValues[index] = os.str();
|
||||||
|
if (_handle->debug())
|
||||||
|
{
|
||||||
|
std::cerr << "PostgreSQL debug: binding time parameter string: " << _handle->paramValues[index] << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void prepared_statement_t::_bind_date_time_parameter(size_t index, const ::sqlpp::chrono::microsecond_point* value, bool is_null)
|
inline void prepared_statement_t::_bind_date_time_parameter(size_t index, const ::sqlpp::chrono::microsecond_point* value, bool is_null)
|
||||||
{
|
{
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#include <sqlpp11/postgresql/postgresql.h>
|
#include <sqlpp11/postgresql/postgresql.h>
|
||||||
#include <sqlpp11/sqlpp11.h>
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
#include "TabFoo.h"
|
#include "TabDateTime.h"
|
||||||
#include "make_test_connection.h"
|
#include "make_test_connection.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -39,6 +39,7 @@ namespace
|
|||||||
const auto now = ::date::floor<::std::chrono::microseconds>(std::chrono::system_clock::now());
|
const auto now = ::date::floor<::std::chrono::microseconds>(std::chrono::system_clock::now());
|
||||||
const auto today = ::date::floor<::sqlpp::chrono::days>(now);
|
const auto today = ::date::floor<::sqlpp::chrono::days>(now);
|
||||||
const auto yesterday = today - ::sqlpp::chrono::days{1};
|
const auto yesterday = today - ::sqlpp::chrono::days{1};
|
||||||
|
const auto current = now - today;
|
||||||
|
|
||||||
template <typename L, typename R>
|
template <typename L, typename R>
|
||||||
auto require_equal(int line, const L& l, const R& r) -> void
|
auto require_equal(int line, const L& l, const R& r) -> void
|
||||||
@ -60,18 +61,15 @@ int DateTime(int, char*[])
|
|||||||
|
|
||||||
sql::connection db = sql::make_test_connection();
|
sql::connection db = sql::make_test_connection();
|
||||||
|
|
||||||
db.execute(R"(DROP TABLE IF EXISTS tabfoo;)");
|
db.execute(R"(DROP TABLE IF EXISTS tabdatetime;)");
|
||||||
db.execute(R"(CREATE TABLE tabfoo
|
db.execute(R"(CREATE TABLE tabdatetime
|
||||||
(
|
(
|
||||||
alpha bigserial NOT NULL,
|
|
||||||
beta smallint,
|
|
||||||
gamma text,
|
|
||||||
c_bool boolean,
|
|
||||||
c_timepoint timestamp with time zone,
|
c_timepoint timestamp with time zone,
|
||||||
|
c_time time with time zone,
|
||||||
c_day date
|
c_day date
|
||||||
))");
|
))");
|
||||||
|
|
||||||
model::TabFoo tab = {};
|
model::TabDateTime tab = {};
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
db(insert_into(tab).default_values());
|
db(insert_into(tab).default_values());
|
||||||
@ -79,15 +77,18 @@ int DateTime(int, char*[])
|
|||||||
{
|
{
|
||||||
require_equal(__LINE__, row.c_day.is_null(), true);
|
require_equal(__LINE__, row.c_day.is_null(), true);
|
||||||
require_equal(__LINE__, row.c_day.value(), ::sqlpp::chrono::day_point{});
|
require_equal(__LINE__, row.c_day.value(), ::sqlpp::chrono::day_point{});
|
||||||
|
require_equal(__LINE__, row.c_time.is_null(), true);
|
||||||
|
require_equal(__LINE__, row.c_time.value(), ::std::chrono::microseconds{});
|
||||||
require_equal(__LINE__, row.c_timepoint.is_null(), true);
|
require_equal(__LINE__, row.c_timepoint.is_null(), true);
|
||||||
require_equal(__LINE__, row.c_timepoint.value(), ::sqlpp::chrono::microsecond_point{});
|
require_equal(__LINE__, row.c_timepoint.value(), ::sqlpp::chrono::microsecond_point{});
|
||||||
}
|
}
|
||||||
|
|
||||||
db(update(tab).set(tab.c_day = today, tab.c_timepoint = now).unconditionally());
|
db(update(tab).set(tab.c_day = today, tab.c_time = current, tab.c_timepoint = now).unconditionally());
|
||||||
|
|
||||||
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
{
|
{
|
||||||
require_equal(__LINE__, row.c_day.value(), today);
|
require_equal(__LINE__, row.c_day.value(), today);
|
||||||
|
require_equal(__LINE__, row.c_time.value(), current);
|
||||||
require_equal(__LINE__, row.c_timepoint.value(), now);
|
require_equal(__LINE__, row.c_timepoint.value(), now);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,14 +97,17 @@ int DateTime(int, char*[])
|
|||||||
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
{
|
{
|
||||||
require_equal(__LINE__, row.c_day.value(), yesterday);
|
require_equal(__LINE__, row.c_day.value(), yesterday);
|
||||||
|
require_equal(__LINE__, row.c_time.value(), current);
|
||||||
require_equal(__LINE__, row.c_timepoint.value(), today);
|
require_equal(__LINE__, row.c_timepoint.value(), today);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto prepared_update =
|
auto prepared_update = db.prepare(update(tab)
|
||||||
db.prepare(update(tab)
|
.set(tab.c_day = parameter(tab.c_day),
|
||||||
.set(tab.c_day = parameter(tab.c_day), tab.c_timepoint = parameter(tab.c_timepoint))
|
tab.c_time = parameter(tab.c_time),
|
||||||
.unconditionally());
|
tab.c_timepoint = parameter(tab.c_timepoint))
|
||||||
|
.unconditionally());
|
||||||
prepared_update.params.c_day = today;
|
prepared_update.params.c_day = today;
|
||||||
|
prepared_update.params.c_time = current;
|
||||||
prepared_update.params.c_timepoint = now;
|
prepared_update.params.c_timepoint = now;
|
||||||
std::cout << "---- running prepared update ----" << std::endl;
|
std::cout << "---- running prepared update ----" << std::endl;
|
||||||
db(prepared_update);
|
db(prepared_update);
|
||||||
@ -111,6 +115,7 @@ int DateTime(int, char*[])
|
|||||||
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
{
|
{
|
||||||
require_equal(__LINE__, row.c_day.value(), today);
|
require_equal(__LINE__, row.c_day.value(), today);
|
||||||
|
require_equal(__LINE__, row.c_time.value(), current);
|
||||||
require_equal(__LINE__, row.c_timepoint.value(), now);
|
require_equal(__LINE__, row.c_timepoint.value(), now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
112
tests/postgresql/usage/TabDateTime.h
Normal file
112
tests/postgresql/usage/TabDateTime.h
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
#ifndef MODEL_TABDATETIME_H
|
||||||
|
#define MODEL_TABDATETIME_H
|
||||||
|
|
||||||
|
#include <sqlpp11/table.h>
|
||||||
|
#include <sqlpp11/char_sequence.h>
|
||||||
|
#include <sqlpp11/column_types.h>
|
||||||
|
|
||||||
|
namespace model
|
||||||
|
{
|
||||||
|
namespace TabDateTime_
|
||||||
|
{
|
||||||
|
struct C_timepoint
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "c_timepoint";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T c_timepoint;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return c_timepoint;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return c_timepoint;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
using _traits = ::sqlpp::make_traits<::sqlpp::time_point, sqlpp::tag::can_be_null>;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct C_day
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "c_day";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T c_day;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return c_day;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return c_day;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
using _traits = ::sqlpp::make_traits<::sqlpp::day_point, sqlpp::tag::can_be_null>;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct C_time
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "c_time";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T c_time;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return c_time;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return c_time;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
using _traits = sqlpp::make_traits<sqlpp::time_of_day, sqlpp::tag::can_be_null>;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace TabDatetime_
|
||||||
|
|
||||||
|
struct TabDateTime : sqlpp::table_t<TabDateTime,
|
||||||
|
TabDateTime_::C_time,
|
||||||
|
TabDateTime_::C_day,
|
||||||
|
TabDateTime_::C_timepoint>
|
||||||
|
{
|
||||||
|
using _value_type = sqlpp::no_value_t;
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "TabDatetime";
|
||||||
|
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
|
Loading…
Reference in New Issue
Block a user