0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-15 20:31:16 +08:00

Merge branch 'release/0.59'

This commit is contained in:
Roland Bock 2020-05-06 22:00:00 +02:00
commit 2b5f8d7666
34 changed files with 488 additions and 83 deletions

View File

@ -4,7 +4,7 @@ os:
- linux - linux
- osx - osx
dist: trusty dist: xenial
sudo: required sudo: required
compiler: compiler:
@ -23,6 +23,7 @@ notifications:
install: install:
- g++ --version - g++ --version
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew upgrade cmake; fi
- cmake --version - cmake --version
- git clone https://github.com/HowardHinnant/date - git clone https://github.com/HowardHinnant/date
- cd date - cd date

View File

@ -165,6 +165,24 @@ brew install marvin182/zapfhahn/sqlpp11
Some connectors can be installed with the formula. See `brew info marvin182/zapfhahn/sqlpp11` for available options. Some connectors can be installed with the formula. See `brew info marvin182/zapfhahn/sqlpp11` for available options.
__Build via vcpkg:__
You can download and install sqlpp11 using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
```bash
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
vcpkg install sqlpp11
```
The sqlpp11 port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
The following connector libraries for sqlpp11 are maintained as a separate package in vcpkg:
* [sqlpp11-connector-sqlite3](https://github.com/microsoft/vcpkg/tree/master/ports/sqlpp11-connector-sqlite3)
* [sqlpp11-connector-mysql](https://github.com/microsoft/vcpkg/tree/master/ports/sqlpp11-connector-mysql)
Basic usage: Basic usage:
------------- -------------

View File

@ -31,15 +31,14 @@ find_dependency(HinnantDate REQUIRED)
include("${CMAKE_CURRENT_LIST_DIR}/Sqlpp11Targets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/Sqlpp11Targets.cmake")
# Import "ddl2cpp" script # Import "ddl2cpp" script
if(TARGET sqlpp11::ddl2cpp) if(NOT TARGET sqlpp11::ddl2cpp)
message(FATAL_ERROR "Target sqlpp11::ddl2cpp already defined") get_filename_component(sqlpp11_ddl2cpp_location "${CMAKE_CURRENT_LIST_DIR}/../../../bin/sqlpp11-ddl2cpp" REALPATH)
if(NOT EXISTS "${sqlpp11_ddl2cpp_location}")
message(FATAL_ERROR "The imported target sqlpp11::ddl2cpp references the file '${sqlpp11_ddl2cpp_location}' but this file does not exists.")
endif()
add_executable(sqlpp11::ddl2cpp IMPORTED)
set_target_properties(sqlpp11::ddl2cpp PROPERTIES
IMPORTED_LOCATION "${sqlpp11_ddl2cpp_location}"
)
unset(sqlpp11_ddl2cpp_location)
endif() endif()
get_filename_component(sqlpp11_ddl2cpp_location "${CMAKE_CURRENT_LIST_DIR}/../../../bin/sqlpp11-ddl2cpp" REALPATH)
if(NOT EXISTS "${sqlpp11_ddl2cpp_location}")
message(FATAL_ERROR "The imported target sqlpp11::ddl2cpp references the file '${sqlpp11_ddl2cpp_location}' but this file does not exists.")
endif()
add_executable(sqlpp11::ddl2cpp IMPORTED)
set_target_properties(sqlpp11::ddl2cpp PROPERTIES
IMPORTED_LOCATION "${sqlpp11_ddl2cpp_location}"
)
unset(sqlpp11_ddl2cpp_location)

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2013-2020, Roland Bock, MacDue
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP11_AGGREGATE_FUNCTION_OPERATORS_H
#define SQLPP11_AGGREGATE_FUNCTION_OPERATORS_H
namespace sqlpp
{
template <typename Expr>
struct aggregate_function_operators
{
over_t<Expr> over() const
{
return {*static_cast<const Expr*>(this)};
}
};
} // namespace sqlpp
#endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2016, Roland Bock * Copyright (c) 2013-2020, Roland Bock, MacDue
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -56,6 +56,7 @@ namespace sqlpp
template <typename Flag, typename Expr> template <typename Flag, typename Expr>
struct avg_t : public expression_operators<avg_t<Flag, Expr>, floating_point>, struct avg_t : public expression_operators<avg_t<Flag, Expr>, floating_point>,
public aggregate_function_operators<avg_t<Flag, Expr>>,
public alias_operators<avg_t<Flag, Expr>> public alias_operators<avg_t<Flag, Expr>>
{ {
using _traits = make_traits<floating_point, tag::is_expression, tag::is_selectable>; using _traits = make_traits<floating_point, tag::is_expression, tag::is_selectable>;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2015, Roland Bock * Copyright (c) 2013-2020, Roland Bock, MacDue
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -27,8 +27,10 @@
#ifndef SQLPP11_AGGREGATE_FUNCTIONS_COUNT_H #ifndef SQLPP11_AGGREGATE_FUNCTIONS_COUNT_H
#define SQLPP11_AGGREGATE_FUNCTIONS_COUNT_H #define SQLPP11_AGGREGATE_FUNCTIONS_COUNT_H
#include <sqlpp11/over.h>
#include <sqlpp11/char_sequence.h> #include <sqlpp11/char_sequence.h>
#include <sqlpp11/select_flags.h> #include <sqlpp11/select_flags.h>
#include <sqlpp11/aggregate_function_operators.h>
#include <sqlpp11/data_types/integral/data_type.h> #include <sqlpp11/data_types/integral/data_type.h>
namespace sqlpp namespace sqlpp
@ -57,6 +59,7 @@ namespace sqlpp
template <typename Flag, typename Expr> template <typename Flag, typename Expr>
struct count_t : public expression_operators<count_t<Flag, Expr>, integral>, struct count_t : public expression_operators<count_t<Flag, Expr>, integral>,
public aggregate_function_operators<count_t<Flag, Expr>>,
public alias_operators<count_t<Flag, Expr>> public alias_operators<count_t<Flag, Expr>>
{ {
using _traits = make_traits<integral, tag::is_expression /*, tag::is_selectable*/>; using _traits = make_traits<integral, tag::is_expression /*, tag::is_selectable*/>;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2015, Roland Bock * Copyright (c) 2013-2020, Roland Bock, MacDue
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -55,7 +55,9 @@ namespace sqlpp
}; };
template <typename Expr> template <typename Expr>
struct max_t : public expression_operators<max_t<Expr>, value_type_of<Expr>>, public alias_operators<max_t<Expr>> struct max_t : public expression_operators<max_t<Expr>, value_type_of<Expr>>,
public aggregate_function_operators<max_t<Expr>>,
public alias_operators<max_t<Expr>>
{ {
using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>; using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>;
using _nodes = detail::type_vector<Expr, aggregate_function>; using _nodes = detail::type_vector<Expr, aggregate_function>;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2015, Roland Bock * Copyright (c) 2013-2020, Roland Bock, MacDue
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -55,7 +55,9 @@ namespace sqlpp
}; };
template <typename Expr> template <typename Expr>
struct min_t : public expression_operators<min_t<Expr>, value_type_of<Expr>>, public alias_operators<min_t<Expr>> struct min_t : public expression_operators<min_t<Expr>, value_type_of<Expr>>,
public aggregate_function_operators<min_t<Expr>>,
public alias_operators<min_t<Expr>>
{ {
using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>; using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>;
using _nodes = detail::type_vector<Expr, aggregate_function>; using _nodes = detail::type_vector<Expr, aggregate_function>;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2015, Roland Bock * Copyright (c) 2013-2020, Roland Bock, MacDue
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -56,6 +56,7 @@ namespace sqlpp
template <typename Flag, typename Expr> template <typename Flag, typename Expr>
struct sum_t : public expression_operators<sum_t<Flag, Expr>, value_type_of<Expr>>, struct sum_t : public expression_operators<sum_t<Flag, Expr>, value_type_of<Expr>>,
public aggregate_function_operators<sum_t<Flag, Expr>>,
public alias_operators<sum_t<Flag, Expr>> public alias_operators<sum_t<Flag, Expr>>
{ {
using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>; using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>;

View File

@ -183,7 +183,7 @@ namespace sqlpp
try try
{ {
auto c = std::unique_ptr<Connection>(new Connection(*(config.get()))); auto c = std::unique_ptr<Connection>(new Connection(config));
return pool_connection<Connection_config, Reconnect_policy, Connection>(c, this); return pool_connection<Connection_config, Reconnect_policy, Connection>(c, this);
} }
catch (const sqlpp::exception& e) catch (const sqlpp::exception& e)

View File

@ -163,6 +163,7 @@ namespace sqlpp
{ {
using _traits = make_traits<no_value_t, tag::is_cte, tag::is_table>; // FIXME: is table? really? using _traits = make_traits<no_value_t, tag::is_cte, tag::is_table>; // FIXME: is table? really?
using _nodes = detail::type_vector<>; using _nodes = detail::type_vector<>;
using _provided_tables = detail::type_set<cte_t>;
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Statement>, detail::type_set<AliasProvider>>; using _required_ctes = detail::make_joined_set_t<required_ctes_of<Statement>, detail::type_set<AliasProvider>>;
using _parameters = parameters_of<Statement>; using _parameters = parameters_of<Statement>;

View File

@ -28,6 +28,7 @@
#define SQLPP_BLOB_DATA_TYPE_H #define SQLPP_BLOB_DATA_TYPE_H
#include <vector> #include <vector>
#include <cstdint>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/logic.h> #include <sqlpp11/logic.h>

View File

@ -48,14 +48,14 @@ namespace sqlpp
struct return_type_plus<L, R, binary_operand_check_t<L, is_unsigned_integral_t, R, is_numeric_t>> struct return_type_plus<L, R, binary_operand_check_t<L, is_unsigned_integral_t, R, is_numeric_t>>
{ {
using check = consistent_t; using check = consistent_t;
using type = value_type_of<wrap_operand_t<R>>; using type = plus_t<wrap_operand_t<L>, value_type_of<wrap_operand_t<R>>, wrap_operand_t<R>>;
}; };
template <typename L, typename R> template <typename L, typename R>
struct return_type_minus<L, R, binary_operand_check_t<L, is_unsigned_integral_t, R, is_numeric_not_unsigned_t>> struct return_type_minus<L, R, binary_operand_check_t<L, is_unsigned_integral_t, R, is_numeric_not_unsigned_t>>
{ {
using check = consistent_t; using check = consistent_t;
using type = value_type_of<wrap_operand_t<R>>; using type = minus_t<wrap_operand_t<L>, value_type_of<wrap_operand_t<R>>, wrap_operand_t<R>>;
}; };
template <typename L, typename R> template <typename L, typename R>
@ -69,14 +69,14 @@ namespace sqlpp
struct return_type_multiplies<L, R, binary_operand_check_t<L, is_unsigned_integral_t, R, is_numeric_t>> struct return_type_multiplies<L, R, binary_operand_check_t<L, is_unsigned_integral_t, R, is_numeric_t>>
{ {
using check = consistent_t; using check = consistent_t;
using type = value_type_of<wrap_operand_t<R>>; using type = multiplies_t<wrap_operand_t<L>, value_type_of<wrap_operand_t<R>>, wrap_operand_t<R>>;
}; };
template <typename L, typename R> template <typename L, typename R>
struct return_type_divides<L, R, binary_operand_check_t<L, is_unsigned_integral_t, R, is_numeric_t>> struct return_type_divides<L, R, binary_operand_check_t<L, is_unsigned_integral_t, R, is_numeric_t>>
{ {
using check = consistent_t; using check = consistent_t;
using type = value_type_of<wrap_operand_t<R>>; using type = divides_t<wrap_operand_t<L>, wrap_operand_t<R>>;
}; };
template <typename L, typename R> template <typename L, typename R>

View File

@ -28,6 +28,7 @@
#define SQLPP11_DETAIL_TYPE_SET_H #define SQLPP11_DETAIL_TYPE_SET_H
#include <type_traits> #include <type_traits>
#include <stddef.h>
#include <sqlpp11/wrong.h> #include <sqlpp11/wrong.h>
#include <sqlpp11/logic.h> #include <sqlpp11/logic.h>

View File

@ -98,7 +98,17 @@ namespace sqlpp
struct minus struct minus
{ {
using _traits = make_traits<ValueType>; using _traits = make_traits<ValueType>;
static constexpr const char* _name = "-"; // The trailing space is necessary to prevent
// ```
// t.id - -1
// ```
// from turning into
// ```
// tab_sample.id--1
// ```
// (-- starts a comment in SQL)
// See https://github.com/rbock/sqlpp11/issues/294
static constexpr const char* _name = " - ";
}; };
template <typename ValueType> template <typename ValueType>

73
include/sqlpp11/over.h Normal file
View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2013-2020, Roland Bock, MacDue
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP11_OVER_H
#define SQLPP11_OVER_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/serializer.h>
namespace sqlpp
{
template <typename AggregateExpr>
struct over_t : public expression_operators<over_t<AggregateExpr>, integral>,
public alias_operators<over_t<AggregateExpr>>
{
using _traits = make_traits<integral, tag::is_expression>;
using _nodes = detail::type_vector<AggregateExpr, aggregate_function>;
using _auto_alias_t = typename AggregateExpr::_auto_alias_t;
over_t(AggregateExpr aggregate_expression)
: _aggregate_expression(aggregate_expression)
{
}
over_t(const over_t&) = default;
over_t(over_t&&) = default;
over_t& operator=(const over_t&) = default;
over_t& operator=(over_t&&) = default;
~over_t() = default;
AggregateExpr _aggregate_expression;
};
template <typename Context, typename AggregateExpr>
struct serializer_t<Context, over_t<AggregateExpr>>
{
using _serialize_check = serialize_check_of<Context, AggregateExpr>;
using T = over_t<AggregateExpr>;
static Context& _(const T& t, Context& context)
{
serialize_operand(t._aggregate_expression, context);
context << " OVER()";
return context;
}
};
} // namespace sqlpp
#endif

View File

@ -30,6 +30,7 @@
#include <sqlpp11/join_types.h> #include <sqlpp11/join_types.h>
#include <sqlpp11/noop.h> #include <sqlpp11/noop.h>
#include <sqlpp11/on.h> #include <sqlpp11/on.h>
#include <sqlpp11/table_ref.h>
namespace sqlpp namespace sqlpp
{ {
@ -154,7 +155,7 @@ namespace sqlpp
auto join_impl(Check, Lhs lhs, Rhs rhs) -> inconsistent<Check>; auto join_impl(Check, Lhs lhs, Rhs rhs) -> inconsistent<Check>;
template <typename JoinType, typename Lhs, typename Rhs> template <typename JoinType, typename Lhs, typename Rhs>
auto join_impl(consistent_t, Lhs lhs, Rhs rhs) -> pre_join_t<JoinType, Lhs, Rhs>; auto join_impl(consistent_t, Lhs lhs, Rhs rhs) -> pre_join_t<JoinType, from_table_t<Lhs>, from_table_t<Rhs>>;
template <typename JoinType, typename Lhs, typename Rhs> template <typename JoinType, typename Lhs, typename Rhs>
auto join_impl(Lhs lhs, Rhs rhs) -> decltype(join_impl<JoinType>(check_pre_join_t<Lhs, Rhs>{}, lhs, rhs)); auto join_impl(Lhs lhs, Rhs rhs) -> decltype(join_impl<JoinType>(check_pre_join_t<Lhs, Rhs>{}, lhs, rhs));
@ -163,19 +164,19 @@ namespace sqlpp
template <typename Lhs, typename Rhs> template <typename Lhs, typename Rhs>
auto join(Lhs lhs, Rhs rhs) -> decltype(detail::join_impl<inner_join_t>(lhs, rhs)) auto join(Lhs lhs, Rhs rhs) -> decltype(detail::join_impl<inner_join_t>(lhs, rhs))
{ {
return {lhs, rhs}; return {from_table(lhs), from_table(rhs)};
} }
template <typename Lhs, typename Rhs> template <typename Lhs, typename Rhs>
auto inner_join(Lhs lhs, Rhs rhs) -> decltype(detail::join_impl<inner_join_t>(lhs, rhs)) auto inner_join(Lhs lhs, Rhs rhs) -> decltype(detail::join_impl<inner_join_t>(lhs, rhs))
{ {
return {lhs, rhs}; return {from_table(lhs), from_table(rhs)};
} }
template <typename Lhs, typename Rhs> template <typename Lhs, typename Rhs>
auto left_outer_join(Lhs lhs, Rhs rhs) -> decltype(detail::join_impl<left_outer_join_t>(lhs, rhs)) auto left_outer_join(Lhs lhs, Rhs rhs) -> decltype(detail::join_impl<left_outer_join_t>(lhs, rhs))
{ {
return {lhs, rhs}; return {from_table(lhs), from_table(rhs)};
} }
template <typename Lhs, typename Rhs> template <typename Lhs, typename Rhs>
@ -183,13 +184,13 @@ namespace sqlpp
{ {
check_pre_join_t<Lhs, Rhs>{}; check_pre_join_t<Lhs, Rhs>{};
return {lhs, rhs}; return {from_table(lhs), from_table(rhs)};
} }
template <typename Lhs, typename Rhs> template <typename Lhs, typename Rhs>
auto outer_join(Lhs lhs, Rhs rhs) -> decltype(detail::join_impl<outer_join_t>(lhs, rhs)) auto outer_join(Lhs lhs, Rhs rhs) -> decltype(detail::join_impl<outer_join_t>(lhs, rhs))
{ {
return {lhs, rhs}; return {from_table(lhs), from_table(rhs)};
} }
namespace detail namespace detail
@ -202,13 +203,14 @@ namespace sqlpp
-> join_t<pre_join_t<cross_join_t, Lhs, Rhs>, on_t<unconditional_t>>; -> join_t<pre_join_t<cross_join_t, Lhs, Rhs>, on_t<unconditional_t>>;
template <typename Lhs, typename Rhs> template <typename Lhs, typename Rhs>
auto cross_join_impl(Lhs lhs, Rhs rhs) -> decltype(cross_join_impl(check_pre_join_t<Lhs, Rhs>{}, lhs, rhs)); auto cross_join_impl(Lhs lhs, Rhs rhs)
-> decltype(cross_join_impl(check_pre_join_t<from_table_t<Lhs>, from_table_t<Rhs>>{}, lhs, rhs));
} // namespace detail } // namespace detail
template <typename Lhs, typename Rhs> template <typename Lhs, typename Rhs>
auto cross_join(Lhs lhs, Rhs rhs) -> decltype(detail::cross_join_impl(lhs, rhs)) auto cross_join(Lhs lhs, Rhs rhs) -> decltype(detail::cross_join_impl(lhs, rhs))
{ {
return {pre_join_t<cross_join_t, Lhs, Rhs>{lhs, rhs}, {}}; return {pre_join_t<cross_join_t, from_table_t<Lhs>, from_table_t<Rhs>>{from_table(lhs), from_table(rhs)}, {}};
} }
} // namespace sqlpp } // namespace sqlpp

View File

@ -57,12 +57,11 @@ namespace sqlpp
}; };
template <typename Flag, typename Expr> template <typename Flag, typename Expr>
struct trim_t : public expression_operators<trim_t<Flag, Expr>, text>, struct trim_t : public expression_operators<trim_t<Flag, Expr>, text>, public alias_operators<trim_t<Flag, Expr>>
public alias_operators<trim_t<Flag, Expr>>
{ {
using _traits = make_traits<text, tag::is_expression, tag::is_selectable>; using _traits = make_traits<text, tag::is_expression, tag::is_selectable>;
using _nodes = detail::type_vector<Expr, aggregate_function>; using _nodes = detail::type_vector<Expr>;
using _can_be_null = can_be_null_t<Expr>; using _can_be_null = can_be_null_t<Expr>;
using _is_aggregate_expression = std::false_type; using _is_aggregate_expression = std::false_type;
@ -94,7 +93,6 @@ namespace sqlpp
context << ")"; context << ")";
return context; return context;
} }
}; };
template <typename T> template <typename T>

View File

@ -256,6 +256,10 @@ namespace sqlpp
static_check_t<not std::is_same<Database, void>::value, assert_where_dynamic_used_with_dynamic_statement_t>, static_check_t<not std::is_same<Database, void>::value, assert_where_dynamic_used_with_dynamic_statement_t>,
check_where_t<Expression>>; check_where_t<Expression>>;
template <typename Database>
using check_where_empty_dynamic_t = static_combined_check_t<
static_check_t<not std::is_same<Database, void>::value, assert_where_dynamic_used_with_dynamic_statement_t>>;
// NO WHERE YET // NO WHERE YET
template <bool WhereRequired> template <bool WhereRequired>
struct no_where_t struct no_where_t
@ -338,10 +342,11 @@ namespace sqlpp
return _where_impl<_database_t>(Check{}, expression); return _where_impl<_database_t>(Check{}, expression);
} }
auto dynamic_where() const -> _new_statement_t<check_where_dynamic_t<_database_t, boolean_operand>, auto dynamic_where() const
where_t<_database_t, boolean_operand>> -> _new_statement_t<check_where_empty_dynamic_t<_database_t>, where_t<_database_t, unconditional_t>>
{ {
return dynamic_where(::sqlpp::value(true)); return {static_cast<const derived_statement_t<Policies>&>(*this),
where_data_t<_database_t, unconditional_t>{unconditional_t{}}};
} }
private: private:
@ -378,6 +383,24 @@ namespace sqlpp
} }
}; };
template <typename Context, typename Database>
struct serializer_t<Context, where_data_t<Database, unconditional_t>>
{
using _serialize_check = consistent_t;
using T = where_data_t<Database, unconditional_t>;
static Context& _(const T& t, Context& context)
{
if (t._dynamic_expressions.empty())
{
return context;
}
context << " WHERE ";
interpret_list(t._dynamic_expressions, " AND ", context);
return context;
}
};
template <typename Context> template <typename Context>
struct serializer_t<Context, where_data_t<void, unconditional_t>> struct serializer_t<Context, where_data_t<void, unconditional_t>>
{ {
@ -403,6 +426,13 @@ namespace sqlpp
return statement_t<Database, no_where_t<false>>().dynamic_where(std::forward<T>(t)); return statement_t<Database, no_where_t<false>>().dynamic_where(std::forward<T>(t));
} }
template <typename Database>
auto dynamic_where(const Database & /*unused*/)
-> decltype(statement_t<Database, no_where_t<false>>().dynamic_where())
{
return statement_t<Database, no_where_t<false>>().dynamic_where();
}
inline auto unconditionally() -> decltype(statement_t<void, no_where_t<false>>().unconditionally()) inline auto unconditionally() -> decltype(statement_t<void, no_where_t<false>>().unconditionally())
{ {
return statement_t<void, no_where_t<false>>().unconditionally(); return statement_t<void, no_where_t<false>>().unconditionally();

View File

@ -273,6 +273,7 @@ types = {
'numeric': 'floating_point', # PostgreSQL 'numeric': 'floating_point', # PostgreSQL
'date': 'day_point', 'date': 'day_point',
'datetime': 'time_point', 'datetime': 'time_point',
'time': 'time_of_day',
'time without time zone': 'time_point', # PostgreSQL 'time without time zone': 'time_point', # PostgreSQL
'time with time zone': 'time_point', # PostgreSQL 'time with time zone': 'time_point', # PostgreSQL
'timestamp': 'time_point', 'timestamp': 'time_point',
@ -311,6 +312,8 @@ nsList = namespace.split('::')
def escape_if_reserved(name): def escape_if_reserved(name):
reserved_names = [ reserved_names = [
'BEGIN',
'END',
'GROUP', 'GROUP',
'ORDER', 'ORDER',
] ]

View File

@ -48,6 +48,11 @@ def main():
parser.add_argument('ddl', help='path to ddl') parser.add_argument('ddl', help='path to ddl')
parser.add_argument('target', help='path to target') parser.add_argument('target', help='path to target')
parser.add_argument('namespace', help='namespace') parser.add_argument('namespace', help='namespace')
parser.add_argument('-identity-naming',
help='Use table and column names from the ddl '
'(defaults to UpperCamelCase for tables and '
'lowerCamelCase for columns)',
action='store_true')
args = parser.parse_args() args = parser.parse_args()
pathToHeader = args.target + '.h' pathToHeader = args.target + '.h'
@ -57,8 +62,8 @@ def main():
conn.executescript(open(args.ddl).read()) conn.executescript(open(args.ddl).read())
# set vars # set vars
toClassName = class_name_naming_func toClassName = identity_naming_func if args.identity_naming else class_name_naming_func
toMemberName = member_name_naming_func toMemberName = identity_naming_func if args.identity_naming else member_name_naming_func
DataTypeError = False DataTypeError = False
header = open(pathToHeader, 'w') header = open(pathToHeader, 'w')
@ -173,6 +178,9 @@ def get_include_guard_name(namespace, inputfile):
val = re.sub("[^A-Za-z0-9]+", "_", namespace + '_' + os.path.basename(inputfile)) val = re.sub("[^A-Za-z0-9]+", "_", namespace + '_' + os.path.basename(inputfile))
return val.upper() return val.upper()
def identity_naming_func(s):
return s
def repl_camel_case_func(m): def repl_camel_case_func(m):
if m.group(1) == '_': if m.group(1) == '_':
return m.group(2).upper() return m.group(2).upper()

View File

@ -22,11 +22,11 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
include(FindPythonInterp) include(FindPython3)
if (${PYTHONINTERP_FOUND}) if (${Python3_Interpreter_FOUND})
execute_process( execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "import pyparsing" COMMAND ${Python3_EXECUTABLE} -c "import pyparsing"
RESULT_VARIABLE PythonRESULT RESULT_VARIABLE PythonRESULT
OUTPUT_VARIABLE PythonOUTPUT OUTPUT_VARIABLE PythonOUTPUT
ERROR_VARIABLE PythonERROR ERROR_VARIABLE PythonERROR
@ -39,21 +39,21 @@ if (${PYTHONINTERP_FOUND})
message(STATUS "Pyparsing is installed: Enabling ddl2cpp tests.") message(STATUS "Pyparsing is installed: Enabling ddl2cpp tests.")
add_test(NAME sqlpp11.test.ddl2cpp.bad_will_fail add_test(NAME sqlpp11.test.ddl2cpp.bad_will_fail
COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_LIST_DIR}/../scripts/ddl2cpp" -fail-on-parse COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_LIST_DIR}/../scripts/ddl2cpp" -fail-on-parse
"${CMAKE_CURRENT_LIST_DIR}/ddl2cpp_sample_bad.sql" "${CMAKE_CURRENT_LIST_DIR}/ddl2cpp_sample_bad.sql"
"${CMAKE_CURRENT_BINARY_DIR}/fail" "${CMAKE_CURRENT_BINARY_DIR}/fail"
test) test)
set_tests_properties(sqlpp11.test.ddl2cpp.bad_will_fail PROPERTIES WILL_FAIL 1) set_tests_properties(sqlpp11.test.ddl2cpp.bad_will_fail PROPERTIES WILL_FAIL 1)
add_test(NAME sqlpp11.test.ddl2cpp.bad_has_parse_error add_test(NAME sqlpp11.test.ddl2cpp.bad_has_parse_error
COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_LIST_DIR}/../scripts/ddl2cpp" -fail-on-parse COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_LIST_DIR}/../scripts/ddl2cpp" -fail-on-parse
"${CMAKE_CURRENT_LIST_DIR}/ddl2cpp_sample_bad.sql" "${CMAKE_CURRENT_LIST_DIR}/ddl2cpp_sample_bad.sql"
"${CMAKE_CURRENT_BINARY_DIR}/fail" "${CMAKE_CURRENT_BINARY_DIR}/fail"
test) test)
set_tests_properties(sqlpp11.test.ddl2cpp.bad_has_parse_error PROPERTIES PASS_REGULAR_EXPRESSION "Parsing error,.*") set_tests_properties(sqlpp11.test.ddl2cpp.bad_has_parse_error PROPERTIES PASS_REGULAR_EXPRESSION "Parsing error,.*")
add_test(NAME sqlpp11.test.ddl2cpp.good_succeeds add_test(NAME sqlpp11.test.ddl2cpp.good_succeeds
COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_LIST_DIR}/../scripts/ddl2cpp" -fail-on-parse COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_LIST_DIR}/../scripts/ddl2cpp" -fail-on-parse
"${CMAKE_CURRENT_LIST_DIR}/ddl2cpp_sample_good.sql" "${CMAKE_CURRENT_LIST_DIR}/ddl2cpp_sample_good.sql"
"${CMAKE_CURRENT_BINARY_DIR}/fail" "${CMAKE_CURRENT_BINARY_DIR}/fail"
test) test)
@ -67,7 +67,7 @@ if (${PYTHONINTERP_FOUND})
endif() endif()
add_custom_command( add_custom_command(
OUTPUT "${sqlpp.test.generated.sample.include}.h" OUTPUT "${sqlpp.test.generated.sample.include}.h"
COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_LIST_DIR}/../scripts/ddl2cpp" COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_LIST_DIR}/../scripts/ddl2cpp"
${use_identity_naming} ${use_identity_naming}
"${CMAKE_CURRENT_LIST_DIR}/ddl2cpp_sample_good.sql" "${CMAKE_CURRENT_LIST_DIR}/ddl2cpp_sample_good.sql"
"${sqlpp.test.generated.sample.include}" "${sqlpp.test.generated.sample.include}"

View File

@ -31,18 +31,18 @@
SQLPP_ALIAS_PROVIDER(cheese) SQLPP_ALIAS_PROVIDER(cheese)
int As(int, char* []) int As(int, char*[])
{ {
const auto foo = test::TabFoo{}; const auto foo = test::TabFoo{};
const auto bar = test::TabBar{}; const auto bar = test::TabBar{};
compare(__LINE__, foo.omega.as(cheese), "tab_foo.omega AS cheese"); compare(__LINE__, foo.omega.as(cheese), "tab_foo.omega AS cheese");
compare(__LINE__, (foo.omega + 17).as(cheese), "(tab_foo.omega+17) AS cheese"); compare(__LINE__, (foo.omega + 17).as(cheese), "(tab_foo.omega+17) AS cheese");
compare(__LINE__, (foo.omega - 17).as(cheese), "(tab_foo.omega-17) AS cheese"); compare(__LINE__, (foo.omega - 17).as(cheese), "(tab_foo.omega - 17) AS cheese");
compare(__LINE__, (foo.omega - uint32_t(17)).as(cheese), "(tab_foo.omega-17) AS cheese"); compare(__LINE__, (foo.omega - uint32_t(17)).as(cheese), "(tab_foo.omega - 17) AS cheese");
compare(__LINE__, (foo.omega - bar.alpha).as(cheese), "(tab_foo.omega-tab_bar.alpha) AS cheese"); compare(__LINE__, (foo.omega - bar.alpha).as(cheese), "(tab_foo.omega - tab_bar.alpha) AS cheese");
compare(__LINE__, (count(foo.omega) - bar.alpha).as(cheese), "(COUNT(tab_foo.omega)-tab_bar.alpha) AS cheese"); compare(__LINE__, (count(foo.omega) - bar.alpha).as(cheese), "(COUNT(tab_foo.omega) - tab_bar.alpha) AS cheese");
compare(__LINE__, (count(foo.omega) - uint32_t(17)).as(cheese), "(COUNT(tab_foo.omega)-17) AS cheese"); compare(__LINE__, (count(foo.omega) - uint32_t(17)).as(cheese), "(COUNT(tab_foo.omega) - 17) AS cheese");
// Auto alias // Auto alias
compare(__LINE__, select(max(bar.alpha)), "SELECT MAX(tab_bar.alpha) AS max_"); compare(__LINE__, select(max(bar.alpha)), "SELECT MAX(tab_bar.alpha) AS max_");

View File

@ -26,11 +26,13 @@ set(test_serializer_names
As As
Blob Blob
CustomQuery CustomQuery
DynamicWhere
ForUpdate ForUpdate
From From
In In
Insert Insert
TableAlias Over
TableAlias
Where Where
) )
@ -44,7 +46,7 @@ if (SQLPP11_TESTS_CXX_STD)
set_property(TARGET sqlpp11_test_serializer PROPERTY CXX_STANDARD_REQUIRED yes) set_property(TARGET sqlpp11_test_serializer PROPERTY CXX_STANDARD_REQUIRED yes)
set_property(TARGET sqlpp11_test_serializer PROPERTY CXX_EXTENSIONS no) set_property(TARGET sqlpp11_test_serializer PROPERTY CXX_EXTENSIONS no)
endif() endif()
foreach(test_serializer IN LISTS test_serializer_names) foreach(test_serializer IN LISTS test_serializer_names)
add_test(NAME sqlpp11.test_serializer.${test_serializer} add_test(NAME sqlpp11.test_serializer.${test_serializer}
COMMAND sqlpp11_test_serializer ${test_serializer} COMMAND sqlpp11_test_serializer ${test_serializer}

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2016-2019, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "compare.h"
#include "Sample.h"
#include <sqlpp11/sqlpp11.h>
#include <iostream>
int DynamicWhere(int, char*[])
{
const auto bar = test::TabBar{};
auto db = MockDb{};
compare(__LINE__, dynamic_where(db), "");
compare(__LINE__, dynamic_where(db, bar.gamma), " WHERE tab_bar.gamma");
{
auto statement = sqlpp::dynamic_where(db);
statement.where.add(without_table_check(bar.gamma));
compare(__LINE__, statement, " WHERE tab_bar.gamma");
}
{
auto statement = dynamic_where(db, bar.gamma);
statement.where.add(without_table_check(bar.gamma));
compare(__LINE__, statement, " WHERE tab_bar.gamma AND tab_bar.gamma");
}
return 0;
}

50
test_serializer/Over.cpp Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2016-2020, Roland Bock, MacDue
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Sample.h"
#include "compare.h"
#include <sqlpp11/sqlpp11.h>
SQLPP_ALIAS_PROVIDER(dueutil)
int Over(int, char* []) {
auto const foo = test::TabFoo{};
// no/auto alias (wrapped in select so alias is applied)
compare(__LINE__, select(avg(foo.omega).over()), "SELECT AVG(tab_foo.omega) OVER() AS avg_");
compare(__LINE__, select(count(foo.omega).over()), "SELECT COUNT(tab_foo.omega) OVER() AS count_");
compare(__LINE__, select(max(foo.omega).over()), "SELECT MAX(tab_foo.omega) OVER() AS max_");
compare(__LINE__, select(min(foo.omega).over()), "SELECT MIN(tab_foo.omega) OVER() AS min_");
compare(__LINE__, select(sum(foo.omega).over()), "SELECT SUM(tab_foo.omega) OVER() AS sum_");
// alias
compare(__LINE__, avg(foo.omega).over().as(dueutil), "AVG(tab_foo.omega) OVER() AS dueutil");
compare(__LINE__, count(foo.omega).over().as(dueutil), "COUNT(tab_foo.omega) OVER() AS dueutil");
compare(__LINE__, max(foo.omega).over().as(dueutil), "MAX(tab_foo.omega) OVER() AS dueutil");
compare(__LINE__, min(foo.omega).over().as(dueutil), "MIN(tab_foo.omega) OVER() AS dueutil");
compare(__LINE__, sum(foo.omega).over().as(dueutil), "SUM(tab_foo.omega) OVER() AS dueutil");
return 0;
}

View File

@ -42,9 +42,9 @@ namespace
MockDb::_serializer_context_t printer = {}; MockDb::_serializer_context_t printer = {};
return serialize(sqlpp::value(false), printer).str(); return serialize(sqlpp::value(false), printer).str();
} }
} } // namespace
int Where(int, char* []) int Where(int, char*[])
{ {
const auto foo = test::TabFoo{}; const auto foo = test::TabFoo{};
const auto bar = test::TabBar{}; const auto bar = test::TabBar{};
@ -53,6 +53,8 @@ int Where(int, char* [])
compare(__LINE__, select(foo.omega).from(foo).unconditionally(), "SELECT tab_foo.omega FROM tab_foo"); compare(__LINE__, select(foo.omega).from(foo).unconditionally(), "SELECT tab_foo.omega FROM tab_foo");
compare(__LINE__, remove_from(foo).unconditionally(), "DELETE FROM tab_foo"); compare(__LINE__, remove_from(foo).unconditionally(), "DELETE FROM tab_foo");
compare(__LINE__, update(foo).set(foo.omega = 42).unconditionally(), "UPDATE tab_foo SET omega=42"); compare(__LINE__, update(foo).set(foo.omega = 42).unconditionally(), "UPDATE tab_foo SET omega=42");
compare(__LINE__, update(foo).set(foo.omega = foo.omega - -1).unconditionally(),
"UPDATE tab_foo SET omega=(tab_foo.omega - -1)");
compare(__LINE__, where(sqlpp::value(true)), " WHERE " + getTrue()); compare(__LINE__, where(sqlpp::value(true)), " WHERE " + getTrue());
// Never // Never

View File

@ -256,7 +256,6 @@ namespace test
}; };
}; };
}; };
namespace TabDateTime_ namespace TabDateTime_
{ {
struct ColDayPoint struct ColDayPoint
@ -303,7 +302,6 @@ namespace test
}; };
using _traits = sqlpp::make_traits<sqlpp::time_point, sqlpp::tag::can_be_null>; using _traits = sqlpp::make_traits<sqlpp::time_point, sqlpp::tag::can_be_null>;
}; };
struct ColTimeOfDay struct ColTimeOfDay
{ {
struct _alias_t struct _alias_t
@ -333,7 +331,7 @@ namespace test
{ {
struct _alias_t struct _alias_t
{ {
static constexpr const char _literal[] = "tab_time_point"; static constexpr const char _literal[] = "tab_date_time";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>; using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template <typename T> template <typename T>
struct _member_t struct _member_t

View File

@ -61,7 +61,7 @@ void print_row(Row const& row)
std::cout << a << ", " << b << std::endl; std::cout << a << ", " << b << std::endl;
} }
int Select(int, char* []) int Select(int, char*[])
{ {
MockDb db = {}; MockDb db = {};
MockDb::_serializer_context_t printer = {}; MockDb::_serializer_context_t printer = {};
@ -107,11 +107,12 @@ int Select(int, char* [])
std::cout << a << ", " << b << ", " << g << std::endl; std::cout << a << ", " << b << ", " << g << std::endl;
} }
for (const auto& row : db(select(all_of(t).as(t), t.gamma).from(t).where(t.alpha > 7).for_update())) for (const auto& row :
db(select(all_of(t), t.gamma.as(t)).from(t).where(t.alpha > 7 and trim(t.beta) == "test").for_update()))
{ {
int64_t a = row.tabBar.alpha; int64_t a = row.alpha;
const std::string b = row.tabBar.beta; const std::string b = row.beta;
const bool g = row.gamma; const bool g = row.tabBar;
std::cout << a << ", " << b << ", " << g << std::endl; std::cout << a << ", " << b << ", " << g << std::endl;
} }
@ -208,20 +209,19 @@ int Select(int, char* [])
} }
{ {
auto transaction = start_transaction(db, sqlpp::isolation_level::read_committed); auto transaction = start_transaction(db, sqlpp::isolation_level::read_committed);
if (db._mock_data._last_isolation_level != sqlpp::isolation_level::read_committed) if (db._mock_data._last_isolation_level != sqlpp::isolation_level::read_committed)
{ {
std::cout << "Error: transaction isolation level does not match expected level" << std::endl; std::cout << "Error: transaction isolation level does not match expected level" << std::endl;
} }
} }
db.set_default_isolation_level(sqlpp::isolation_level::read_uncommitted); db.set_default_isolation_level(sqlpp::isolation_level::read_uncommitted);
{ {
auto transaction = start_transaction(db); auto transaction = start_transaction(db);
if (db._mock_data._last_isolation_level != sqlpp::isolation_level::read_uncommitted) if (db._mock_data._last_isolation_level != sqlpp::isolation_level::read_uncommitted)
{ {
std::cout << "Error: transaction isolation level does not match default level" << std::endl; std::cout << "Error: transaction isolation level does not match default level" << std::endl;
} }
} }
return 0; return 0;

View File

@ -39,9 +39,9 @@ namespace alias
SQLPP_ALIAS_PROVIDER(b) SQLPP_ALIAS_PROVIDER(b)
SQLPP_ALIAS_PROVIDER(left) SQLPP_ALIAS_PROVIDER(left)
SQLPP_ALIAS_PROVIDER(right) SQLPP_ALIAS_PROVIDER(right)
} } // namespace alias
int SelectType(int, char* []) int SelectType(int, char*[])
{ {
MockDb db = {}; MockDb db = {};
MockDb::_serializer_context_t printer = {}; MockDb::_serializer_context_t printer = {};
@ -163,7 +163,8 @@ int SelectType(int, char* [])
static_assert(sqlpp::is_integral_t<sqlpp::return_type_minus_t<T, sqlpp::integral>>::value, "type requirement"); static_assert(sqlpp::is_integral_t<sqlpp::return_type_minus_t<T, sqlpp::integral>>::value, "type requirement");
static_assert(sqlpp::is_integral_t<sqlpp::return_type_plus_t<T, sqlpp::integral>>::value, "type requirement"); static_assert(sqlpp::is_integral_t<sqlpp::return_type_plus_t<T, sqlpp::integral>>::value, "type requirement");
static_assert(sqlpp::is_integral_t<sqlpp::return_type_multiplies_t<T, sqlpp::integral>>::value, "type requirement"); static_assert(sqlpp::is_integral_t<sqlpp::return_type_multiplies_t<T, sqlpp::integral>>::value, "type requirement");
static_assert(sqlpp::is_integral_t<sqlpp::return_type_divides_t<T, sqlpp::integral>>::value, "type requirement"); static_assert(sqlpp::is_floating_point_t<sqlpp::return_type_divides_t<T, sqlpp::integral>>::value,
"type requirement");
static_assert(sqlpp::is_integral_t<sqlpp::return_type_minus_t<sqlpp::integral, T>>::value, "type requirement"); static_assert(sqlpp::is_integral_t<sqlpp::return_type_minus_t<sqlpp::integral, T>>::value, "type requirement");
static_assert(sqlpp::is_integral_t<sqlpp::return_type_plus_t<sqlpp::integral, T>>::value, "type requirement"); static_assert(sqlpp::is_integral_t<sqlpp::return_type_plus_t<sqlpp::integral, T>>::value, "type requirement");
static_assert(sqlpp::is_integral_t<sqlpp::return_type_multiplies_t<sqlpp::integral, T>>::value, "type requirement"); static_assert(sqlpp::is_integral_t<sqlpp::return_type_multiplies_t<sqlpp::integral, T>>::value, "type requirement");

View File

@ -66,6 +66,9 @@ int Update(int, char*[])
auto values = [&t]() { return std::make_tuple(t.delta += t.alpha, t.beta = "no cake this time"); }; auto values = [&t]() { return std::make_tuple(t.delta += t.alpha, t.beta = "no cake this time"); };
db(update(t).set(t.delta = sqlpp::verbatim<sqlpp::integer>("17+4")).unconditionally()); db(update(t).set(t.delta = sqlpp::verbatim<sqlpp::integer>("17+4")).unconditionally());
db(update(t)
.set(t.delta = sqlpp::verbatim<sqlpp::integer>("17+4"))
.where(sqlpp::verbatim<sqlpp::text>("'hansi'") == "hansi"));
db(update(t).set(t.delta = sqlpp::null).unconditionally()); db(update(t).set(t.delta = sqlpp::null).unconditionally());
db(update(t).set(t.delta = sqlpp::default_value).unconditionally()); db(update(t).set(t.delta = sqlpp::default_value).unconditionally());

View File

@ -55,5 +55,24 @@ int With(int, char*[])
sqlpp::cte(b).as(select(t.alpha.as(a)).from(t).unconditionally().union_all(select(sqlpp::value(123).as(a)))); sqlpp::cte(b).as(select(t.alpha.as(a)).from(t).unconditionally().union_all(select(sqlpp::value(123).as(a))));
db(with(c)(select(all_of(c)).from(c).unconditionally())); db(with(c)(select(all_of(c)).from(c).unconditionally()));
// recursive CTE with join
{
const auto selectBase = select(t.alpha, t.delta).from(t).where(t.alpha > 17);
const auto initialCte = ::sqlpp::cte(sqlpp::alias::a).as(selectBase);
const auto recursiveCte = initialCte.union_all(
select(t.alpha, t.delta).from(t.join(initialCte).on(t.alpha == initialCte.delta)).unconditionally());
const auto query = with(recursiveCte)(select(recursiveCte.alpha).from(recursiveCte).unconditionally());
::MockDb::_serializer_context_t printer = {};
const auto serializedQuery = serialize(query, printer).str();
std::cout << serializedQuery << '\n';
auto db = MockDb{};
for (const auto& row : db(query))
{
std::cout << row.alpha;
}
}
return 0; return 0;
} }

View File

@ -26,10 +26,11 @@
CREATE TABLE IF NOT EXISTS tab_foo CREATE TABLE IF NOT EXISTS tab_foo
( (
delta varchar(255), delta varchar(255) NOT NULL DEFAULT "",
epsilon bigint, epsilon bigint,
omega double, omega double,
psi bigint UNSIGNED psi bigint UNSIGNED,
book BLOB
); );
CREATE TABLE tab_bar CREATE TABLE tab_bar
@ -40,3 +41,10 @@ CREATE TABLE tab_bar
delta int delta int
); );
CREATE TABLE tab_date_time
(
col_day_point date,
col_time_point datetime,
col_time_of_day time
);

73
wishlist.md Normal file
View File

@ -0,0 +1,73 @@
If you want to help with the development of the library, you might want to consider one of these items:
# Better documentation
The documentation in the Wiki is incomplete and outdated. It is also not part of source control, which makes it a bit harder to contribute.
It might make sense to write a couple of markdown files here.
Throw in chapters of how to add features and how to write connector libraries.
## Better tests and examples
Many of the current tests were born when the library was in infant state. Often they test implementation details. And they often just print stuff, instead of checking said stuff.
# Connectors
## Merge stable connectors into sqlpp11
Having all connector libraries in place, makes maintenance considerably simpler, see #174.
It would also reduce the cognitive overhead for newcomers.
## New connectors
There are a couple of connector libraries already. Here are some that have been requested in the past
- Sybase
- Oracle
- SQL Server
- Google Spanner
## More special functions and types for connectors
GROUP CONCAT or JSON support for mysql, for instance
INSERT OR UPDATE for postgresl and mysql
INSERT INTO ... SELECT ... for postgresql
CREATE TABLE for all of them, including PPGEN
Exception types that carry more specific error information, e.g. the native error code, see #227
Find a way to handle column names that are keywords in the vendor's dialect, see #199
Handle specific data types, including JSON for the connectors.
More test cases for DDL files.
# EDSL features
Multi-line insert in prepared statements, see #68
## optional std::optional support
Instead of sqlpp::value_or_null, std::optional would be nice, see #238
## Converter to and from SQL to C++ structs, to allow for more ORM like code
Assuming that you have converter functions from struct to sqlpp11 and back, we could have something like this:
```C++
struct Person;
insert_into(tab).set(Person{});
update(tab).set(Person{});
for (const auto& person : db(select(Person{}).from(tab).unconditionally()))
{
// ...
}
```
# Runtime improvements
## Connection pools and caching interface
In order to support high load scenarios,
- connection pools (to avoid creating and destroying connections)
- caching (hash the query and answer it from the cache for some time), see #86
## Async support
Obtain results in an asynchronous fashion, see #35, for instance.
# Compile time improvements
## Simplify code
See Seventeenification talk. Some of the simplifications can be ported back easily.
## Suppress export of symbols
Some compilers tend to export all the generated symbols, which is a bit annoying in case of template-heavy libraries like sqlpp11 (leads to larger files and longer compile/link/startup times, I believe).
There are ways to suppress this in most compilers, afaik.