diff --git a/include/sqlpp11/alias.h b/include/sqlpp11/alias.h index 0d281e56..0205ac37 100644 --- a/include/sqlpp11/alias.h +++ b/include/sqlpp11/alias.h @@ -90,15 +90,24 @@ namespace sqlpp using _name_t = typename AliasProvider::_name_t; - template - void serialize(std::ostream& os, Db& db) const - { - os << "("; _expression.serialize(os, db); os << ") AS " << _name_t::_get_name(); - } - Expression _expression; }; + template + struct interpreter_t> + { + using T = expression_alias_t; + + static Context& _(const T& t, Context& context) + { + context << '('; + interpret(t._expression, context); + context << ") AS "; + context << T::_name_t::_get_name(); + return context; + } + }; + } #endif diff --git a/include/sqlpp11/detail/basic_operators.h b/include/sqlpp11/detail/basic_operators.h index daaaeae5..8587c046 100644 --- a/include/sqlpp11/detail/basic_operators.h +++ b/include/sqlpp11/detail/basic_operators.h @@ -31,7 +31,7 @@ #include #include #include -#include +#include namespace sqlpp { @@ -110,13 +110,13 @@ namespace sqlpp return { *static_cast(this), {std::forward(t)} }; } - is_null_t is_null() const + is_null_t is_null() const { static_assert(not is_multi_expression_t::value, "multi-expression cannot be used with is_null()"); return { *static_cast(this) }; } - is_null_t is_not_null() const + is_null_t is_not_null() const { static_assert(not is_multi_expression_t::value, "multi-expression cannot be used with is_not_null()"); return { *static_cast(this) }; diff --git a/include/sqlpp11/expression.h b/include/sqlpp11/expression.h index a896bcd4..786ad0d3 100644 --- a/include/sqlpp11/expression.h +++ b/include/sqlpp11/expression.h @@ -231,7 +231,7 @@ namespace sqlpp { context << "("; interpret(t._lhs, context); - context << T::O::_name; + context << O::_name; interpret(t._rhs, context); context << ")"; return context; diff --git a/include/sqlpp11/functions.h b/include/sqlpp11/functions.h index 44e3118a..061cd0ad 100644 --- a/include/sqlpp11/functions.h +++ b/include/sqlpp11/functions.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/include/sqlpp11/is_null.h b/include/sqlpp11/is_null.h index 6da8b1ba..9f5ea931 100644 --- a/include/sqlpp11/is_null.h +++ b/include/sqlpp11/is_null.h @@ -27,7 +27,7 @@ #ifndef SQLPP_IS_NULL_H #define SQLPP_IS_NULL_H -#include +#include #include #include @@ -35,13 +35,12 @@ namespace sqlpp { namespace detail { - // The ValueType should be boolean, this is a hack because boolean is not fully defined when the compiler first gets here... - template - struct is_null_t: public ValueType::_base_value_type::template operators> + template + struct is_null_t: public boolean::template operators> { static constexpr bool _inverted = not NotInverted; - struct _value_type: public ValueType::_base_value_type // we requite fully defined boolean here + struct _value_type: public boolean { using _is_named_expression = std::true_type; }; @@ -70,19 +69,23 @@ namespace sqlpp is_null_t& operator=(is_null_t&&) = default; ~is_null_t() = default; - template - void serialize(std::ostream& os, Db& db) const - { - static_assert((NotInverted and Db::_supports_is_null) - or (_inverted and Db::_supports_is_not_null), "is_null() and/or is_not_null() not supported by current database"); - _operand.serialize(os, db); - os << (_inverted ? " IS NOT NULL" : " IS NULL"); - } - - private: Operand _operand; }; } + + template + struct interpreter_t> + { + using T = detail::is_null_t; + + static Context& _(const T& t, Context& context) + { + interpret(t._operand, context); + context << (t._inverted ? " IS NOT NULL" : " IS NULL"); + return context; + } + }; + } #endif diff --git a/include/sqlpp11/is_null_fwd.h b/include/sqlpp11/is_null_fwd.h new file mode 100644 index 00000000..472ea58e --- /dev/null +++ b/include/sqlpp11/is_null_fwd.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_IS_NULL_FWD_H +#define SQLPP_IS_NULL_FWD_H + +namespace sqlpp +{ + namespace detail + { + template + struct is_null_t; + } +} + +#endif diff --git a/include/sqlpp11/multi_column.h b/include/sqlpp11/multi_column.h index b4327137..398ff341 100644 --- a/include/sqlpp11/multi_column.h +++ b/include/sqlpp11/multi_column.h @@ -52,15 +52,21 @@ namespace sqlpp }; using _is_multi_column = std::true_type; - template - void serialize(std::ostream& os, Db& db) const - { - detail::serialize_tuple(os, db, _columns, ','); - } - std::tuple _columns; }; + template + struct interpreter_t> + { + using T = multi_column_t; + + static Context& _(const T& t, Context& context) + { + interpret_tuple(t._columns, ',', context); + return context; + } + }; + namespace detail { template diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 506d6229..278699a8 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -537,7 +537,7 @@ namespace sqlpp struct _pseudo_table_t { using table = typename ExpressionList::template _pseudo_table_t; - using alias = typename table::template alias_t; + using alias = typename table::template _alias_t; }; template diff --git a/include/sqlpp11/select_pseudo_table.h b/include/sqlpp11/select_pseudo_table.h index 15049b90..9389cb96 100644 --- a/include/sqlpp11/select_pseudo_table.h +++ b/include/sqlpp11/select_pseudo_table.h @@ -49,6 +49,7 @@ namespace sqlpp NamedExpr...>, select_column_spec_t...> { using _value_type = no_value_t; + using _is_pseudo_table = std::true_type; select_pseudo_table_t(const Select& select): _select(select) @@ -66,16 +67,21 @@ namespace sqlpp select_pseudo_table_t& operator=(select_pseudo_table_t&& rhs) = default; ~select_pseudo_table_t() = default; - template - void serialize(std::ostream& os, Db& db) const - { - static_assert(Db::_supports_select_as_table, "select as table not supported by current database"); - _select.serialize(os, db); - } - Select _select; }; + template + struct interpreter_t> + { + using T = select_pseudo_table_t; + + static Context& _(const T& t, Context& context) + { + interpret(t._select, context); + return context; + } + }; + } #endif diff --git a/include/sqlpp11/table.h b/include/sqlpp11/table.h index 1c2106ed..6c549aa0 100644 --- a/include/sqlpp11/table.h +++ b/include/sqlpp11/table.h @@ -46,6 +46,8 @@ namespace sqlpp static_assert(_all_columns::size::value, "at least one column required per table"); using _required_insert_columns = typename detail::make_set_if...>::type; using _all_of_t = std::tuple...>; + template + using _alias_t = table_alias_t::type, Table, ColumnSpec...>; using _is_table = std::true_type; @@ -80,7 +82,7 @@ namespace sqlpp } template - table_alias_t::type, Table, ColumnSpec...> as(const AliasProvider&) const + _alias_t as(const AliasProvider&) const { return {*static_cast(this)}; } @@ -98,13 +100,13 @@ namespace sqlpp } template - struct interpreter_t::value, void>::type> + struct interpreter_t::value and not is_pseudo_table_t::value, void>::type> { using T = X; static Context& _(const T& t, Context& context) { - context << T::_name_t::_get_name(); // FIXME: need a special rule for pseudo tables + context << T::_name_t::_get_name(); return context; } }; diff --git a/include/sqlpp11/table_alias.h b/include/sqlpp11/table_alias.h index 91887b5e..c84e189b 100644 --- a/include/sqlpp11/table_alias.h +++ b/include/sqlpp11/table_alias.h @@ -28,7 +28,7 @@ #define SQLPP_TABLE_ALIAS_H #include -#include +#include #include #include #include diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index 23e1894d..56000008 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -94,6 +94,7 @@ namespace sqlpp SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null); SQLPP_TYPE_TRAIT_GENERATOR(is_table); + SQLPP_TYPE_TRAIT_GENERATOR(is_pseudo_table); SQLPP_TYPE_TRAIT_GENERATOR(is_select); SQLPP_TYPE_TRAIT_GENERATOR(is_select_flag_list); SQLPP_TYPE_TRAIT_GENERATOR(is_select_expression_list); diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index 1bb48793..092be1e5 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -92,5 +92,10 @@ int main() interpret(t.as(t.alpha), printer).flush(); interpret(t.as(t.alpha).beta, printer).flush(); + interpret(multi_column(t.alpha, t.alpha, (t.beta + "cake").as(t.gamma)), printer).flush(); + interpret(t.alpha.is_null(), printer).flush(); + + interpret(select(t.alpha).from(t).where(t.beta > "kaesekuchen").as(t.gamma), printer).flush(); + return 0; }