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_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;
|
||||
@ -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)
|
||||
{
|
||||
|
||||
|
@ -78,6 +78,7 @@ namespace sqlpp
|
||||
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);
|
||||
};
|
||||
@ -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)
|
||||
{
|
||||
if (_handle->debug())
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include <sqlpp11/postgresql/postgresql.h>
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
|
||||
#include "TabFoo.h"
|
||||
#include "TabDateTime.h"
|
||||
#include "make_test_connection.h"
|
||||
|
||||
namespace
|
||||
@ -39,6 +39,7 @@ namespace
|
||||
const auto now = ::date::floor<::std::chrono::microseconds>(std::chrono::system_clock::now());
|
||||
const auto today = ::date::floor<::sqlpp::chrono::days>(now);
|
||||
const auto yesterday = today - ::sqlpp::chrono::days{1};
|
||||
const auto current = now - today;
|
||||
|
||||
template <typename L, typename R>
|
||||
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();
|
||||
|
||||
db.execute(R"(DROP TABLE IF EXISTS tabfoo;)");
|
||||
db.execute(R"(CREATE TABLE tabfoo
|
||||
db.execute(R"(DROP TABLE IF EXISTS tabdatetime;)");
|
||||
db.execute(R"(CREATE TABLE tabdatetime
|
||||
(
|
||||
alpha bigserial NOT NULL,
|
||||
beta smallint,
|
||||
gamma text,
|
||||
c_bool boolean,
|
||||
c_timepoint timestamp with time zone,
|
||||
c_time time with time zone,
|
||||
c_day date
|
||||
))");
|
||||
|
||||
model::TabFoo tab = {};
|
||||
model::TabDateTime tab = {};
|
||||
try
|
||||
{
|
||||
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.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.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()))
|
||||
{
|
||||
require_equal(__LINE__, row.c_day.value(), today);
|
||||
require_equal(__LINE__, row.c_time.value(), current);
|
||||
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()))
|
||||
{
|
||||
require_equal(__LINE__, row.c_day.value(), yesterday);
|
||||
require_equal(__LINE__, row.c_time.value(), current);
|
||||
require_equal(__LINE__, row.c_timepoint.value(), today);
|
||||
}
|
||||
|
||||
auto prepared_update =
|
||||
db.prepare(update(tab)
|
||||
.set(tab.c_day = parameter(tab.c_day), tab.c_timepoint = parameter(tab.c_timepoint))
|
||||
.unconditionally());
|
||||
auto prepared_update = db.prepare(update(tab)
|
||||
.set(tab.c_day = parameter(tab.c_day),
|
||||
tab.c_time = parameter(tab.c_time),
|
||||
tab.c_timepoint = parameter(tab.c_timepoint))
|
||||
.unconditionally());
|
||||
prepared_update.params.c_day = today;
|
||||
prepared_update.params.c_time = current;
|
||||
prepared_update.params.c_timepoint = now;
|
||||
std::cout << "---- running prepared update ----" << std::endl;
|
||||
db(prepared_update);
|
||||
@ -111,6 +115,7 @@ int DateTime(int, char*[])
|
||||
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_time.value(), current);
|
||||
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