diff --git a/include/sqlpp11/column.h b/include/sqlpp11/column.h
index 82d34183..83468e5b 100644
--- a/include/sqlpp11/column.h
+++ b/include/sqlpp11/column.h
@@ -54,11 +54,13 @@ namespace sqlpp
struct _recursive_traits
{
- using _parameters = std::tuple<>;
+ using _required_ctes = detail::type_set<>;
+ using _provided_ctes = detail::type_set<>;
+ using _required_tables = detail::type_set
;
using _provided_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
- using _required_tables = detail::type_set;
using _extra_tables = detail::type_set<>;
+ using _parameters = std::tuple<>;
using _tags = typename std::conditional::value,
detail::type_set,
detail::type_set<>>::type;
diff --git a/include/sqlpp11/count.h b/include/sqlpp11/count.h
index ffe74bc4..1403aa8b 100644
--- a/include/sqlpp11/count.h
+++ b/include/sqlpp11/count.h
@@ -41,6 +41,8 @@ namespace sqlpp
using _traits = make_traits;
struct _recursive_traits
{
+ using _required_ctes = required_ctes_of;
+ using _provided_ctes = detail::type_set<>;
using _required_tables = required_tables_of;
using _provided_tables = provided_tables_of;
using _provided_outer_tables = provided_outer_tables_of;
diff --git a/include/sqlpp11/cte.h b/include/sqlpp11/cte.h
new file mode 100644
index 00000000..af31e09a
--- /dev/null
+++ b/include/sqlpp11/cte.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013-2014, 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_CTE_H
+#define SQLPP_CTE_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace sqlpp
+{
+ template
+ struct pre_cte_t
+ {
+ template
+ auto as(Statement statement)
+ -> cte
+ {
+ // FIXME: Need to check stuff here.
+ return { statement };
+ }
+ };
+
+ template
+ auto cte(const AliasProvider&)
+ -> pre_cte_t
+ {
+ return {};
+ }
+
+}
+
+#endif
diff --git a/include/sqlpp11/extra_tables.h b/include/sqlpp11/extra_tables.h
index 884e1946..cd4e1068 100644
--- a/include/sqlpp11/extra_tables.h
+++ b/include/sqlpp11/extra_tables.h
@@ -54,11 +54,13 @@ namespace sqlpp
using _traits = make_traits;
struct _recursive_traits
{
- using _parameters = std::tuple<>;
+ using _required_ctes = detail::make_joined_set_t...>;
+ using _provided_ctes = detail::type_set<>;
using _required_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
using _provided_tables = detail::type_set<>;
using _extra_tables = detail::type_set;
+ using _parameters = std::tuple<>;
using _tags = detail::type_set<>;
};
diff --git a/include/sqlpp11/join.h b/include/sqlpp11/join.h
index 99dbcdd0..e4dcb97f 100644
--- a/include/sqlpp11/join.h
+++ b/include/sqlpp11/join.h
@@ -68,6 +68,8 @@ namespace sqlpp
using _traits = make_traits;
struct _recursive_traits
{
+ using _required_ctes = detail::make_joined_set_t, required_ctes_of>;
+ using _provided_ctes = detail::type_set<>;
using _required_tables = detail::make_joined_set_t, required_tables_of>;
using _provided_tables = detail::make_joined_set_t, provided_tables_of>;
using _provided_outer_tables = typename JoinType::template _provided_outer_tables;
diff --git a/include/sqlpp11/parameter.h b/include/sqlpp11/parameter.h
index b5daaabc..542a5cb1 100644
--- a/include/sqlpp11/parameter.h
+++ b/include/sqlpp11/parameter.h
@@ -40,11 +40,13 @@ namespace sqlpp
using _traits = make_traits;
struct _recursive_traits
{
- using _parameters = std::tuple;
+ using _required_ctes = detail::type_set<>;
+ using _provided_ctes = detail::type_set<>;
+ using _required_tables = detail::type_set<>;
using _provided_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
- using _required_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
+ using _parameters = std::tuple;
using _tags = detail::type_set;
};
diff --git a/include/sqlpp11/result_field_methods.h b/include/sqlpp11/result_field_methods.h
index 5829ba91..4ab50af9 100644
--- a/include/sqlpp11/result_field_methods.h
+++ b/include/sqlpp11/result_field_methods.h
@@ -83,11 +83,13 @@ namespace sqlpp
struct _recursive_traits
{
- using _parameters = std::tuple<>;
+ using _required_ctes = detail::type_set<>;
+ using _provided_ctes = detail::type_set<>;
+ using _required_tables = detail::type_set<>;
using _provided_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
- using _required_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
+ using _parameters = std::tuple<>;
using _tags = typename std::conditional::value,
detail::type_set,
detail::type_set<>>::type;
diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h
index b663c7d4..89506245 100644
--- a/include/sqlpp11/select.h
+++ b/include/sqlpp11/select.h
@@ -31,6 +31,7 @@
#include
#include
+#include
#include
#include
#include
@@ -69,6 +70,7 @@ namespace sqlpp
template
using blank_select_t = statement_t
struct statement_t;
+ struct assert_no_unknown_ctes_t
+ {
+ using type = std::false_type;
+
+ template
+ static void _()
+ {
+ static_assert(wrong_t::value, "one clause requires common table expressions which are otherwise not known in the statement");
+ }
+ };
+
struct assert_no_unknown_tables_t
{
using type = std::false_type;
@@ -84,6 +95,8 @@ namespace sqlpp
template
using _new_statement_t = typename _policies_update_t::type;
+ using _all_required_ctes = detail::make_joined_set_t...>;
+ using _all_provided_ctes = detail::make_joined_set_t...>;
using _all_required_tables = detail::make_joined_set_t...>;
using _all_provided_tables = detail::make_joined_set_t...>;
using _all_provided_outer_tables = detail::make_joined_set_t...>;
@@ -100,6 +113,12 @@ namespace sqlpp
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
>;
+ // The common table expressions not covered by the with.
+ using _required_ctes = detail::make_difference_set_t<
+ _all_required_ctes,
+ _all_provided_ctes
+ >;
+
using _result_type_provider = detail::get_last_if;
struct _result_methods_t: public _result_type_provider::template _result_methods_t<_statement_t>
@@ -111,7 +130,9 @@ namespace sqlpp
// - the select is complete (leaks no tables)
static constexpr bool _can_be_used_as_table()
{
- return is_select_column_list_t<_result_type_provider>::value and _required_tables::size::value == 0
+ return is_select_column_list_t<_result_type_provider>::value
+ and _required_tables::size::value == 0
+ and _required_ctes::size::value == 0
? true
: false;
}
@@ -133,6 +154,8 @@ namespace sqlpp
struct _recursive_traits
{
+ using _required_ctes = statement_policies_t::_required_ctes;
+ using _provided_ctes = detail::type_set<>;
using _required_tables = statement_policies_t::_required_tables;
using _provided_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
@@ -143,6 +166,8 @@ namespace sqlpp
detail::type_set<>>::type;
};
+ using _cte_check = typename std::conditional<_required_ctes::size::value == 0,
+ consistent_t, assert_no_unknown_ctes_t>::type;
using _table_check = typename std::conditional<_required_tables::size::value == 0,
consistent_t, assert_no_unknown_tables_t>::type;
using _parameter_check = typename std::conditional::value == 0,
@@ -161,10 +186,12 @@ namespace sqlpp
using _run_check = detail::get_first_if::_consistency_check...,
- typename _policies_t::_table_check>;
+ typename _policies_t::_table_check,
+ typename _policies_t::_cte_check>;
using _prepare_check = detail::get_first_if::_consistency_check...,
- typename _policies_t::_table_check>;
+ typename _policies_t::_table_check,
+ typename _policies_t::_cte_check>;
using _result_type_provider = typename _policies_t::_result_type_provider;
template
diff --git a/include/sqlpp11/table.h b/include/sqlpp11/table.h
index b7bd5065..e5e6549c 100644
--- a/include/sqlpp11/table.h
+++ b/include/sqlpp11/table.h
@@ -48,11 +48,13 @@ namespace sqlpp
struct _recursive_traits
{
- using _parameters = std::tuple<>;
+ using _required_ctes = detail::type_set<>;
+ using _provided_ctes = detail::type_set<>;
using _required_tables = detail::type_set<>;
using _provided_tables = detail::type_set;
using _provided_outer_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
+ using _parameters = std::tuple<>;
using _tags = detail::type_set<>;
};
diff --git a/include/sqlpp11/table_alias.h b/include/sqlpp11/table_alias.h
index e7befef0..4985a875 100644
--- a/include/sqlpp11/table_alias.h
+++ b/include/sqlpp11/table_alias.h
@@ -44,11 +44,13 @@ namespace sqlpp
struct _recursive_traits
{
- using _parameters = std::tuple<>;
+ using _required_ctes = required_ctes_of;
+ using _provided_ctes = detail::type_set<>;
using _required_tables = detail::type_set<>;
using _provided_tables = detail::type_set;
using _provided_outer_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
+ using _parameters = std::tuple<>;
using _tags = detail::type_set<>;
};
diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h
index 04ffc42a..4cf352ec 100644
--- a/include/sqlpp11/type_traits.h
+++ b/include/sqlpp11/type_traits.h
@@ -183,6 +183,12 @@ namespace sqlpp
template
using cpp_value_type_of = typename value_type_of::_cpp_value_type;
+ template
+ using required_ctes_of = typename T::_recursive_traits::_required_ctes;
+
+ template
+ using provided_ctes_of = typename T::_recursive_traits::_provided_ctes;
+
template
using required_tables_of = typename T::_recursive_traits::_required_tables;
@@ -217,6 +223,8 @@ namespace sqlpp
template
struct make_recursive_traits
{
+ using _required_ctes = detail::make_joined_set_t...>;
+ using _provided_ctes = detail::make_joined_set_t...>;
using _required_tables = detail::make_joined_set_t...>;
using _provided_tables = detail::make_joined_set_t...>;
using _provided_outer_tables = detail::make_joined_set_t...>;
@@ -228,6 +236,8 @@ namespace sqlpp
template
struct recursive_tags
{
+ using _required_ctes = detail::type_set<>;
+ using _provided_ctes = detail::type_set<>;
using _required_tables = detail::type_set<>;
using _provided_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
diff --git a/include/sqlpp11/union.h b/include/sqlpp11/union.h
index 615321dc..56559421 100644
--- a/include/sqlpp11/union.h
+++ b/include/sqlpp11/union.h
@@ -83,7 +83,7 @@ namespace sqlpp
template
struct union_statement_impl
{
- using type = statement_t;
+ using type = statement_t;
};
template
@@ -208,6 +208,7 @@ namespace sqlpp
auto union_distinct(Rhs rhs) const
-> _new_statement_t<_check, union_t, Rhs>>
{
+#warning: make sure that Rhs is a select, not a uninon
static_assert(is_statement_t::value, "argument of union call has to be a statement");
static_assert(has_result_row_t::value, "argument of a union has to be a (complete) select statement");
static_assert(has_result_row_t>::value, "left hand side argument of a union has to be a (complete) select statement");
diff --git a/include/sqlpp11/with.h b/include/sqlpp11/with.h
new file mode 100644
index 00000000..4811c8d7
--- /dev/null
+++ b/include/sqlpp11/with.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2013-2014, 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_WITH_H
+#define SQLPP_WITH_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace sqlpp
+{
+ template
+ struct with_data_t
+ {
+ with_data_t(Expressions... expressions):
+ _expressions(expressions...)
+ {}
+
+ with_data_t(const with_data_t&) = default;
+ with_data_t(with_data_t&&) = default;
+ with_data_t& operator=(const with_data_t&) = default;
+ with_data_t& operator=(with_data_t&&) = default;
+ ~with_data_t() = default;
+
+ std::tuple _expressions;
+ interpretable_list_t _dynamic_expressions;
+ };
+
+ template
+ struct with_t
+ {
+ using _traits = make_traits;
+ using _recursive_traits = make_recursive_traits;
+
+ using _is_dynamic = is_database;
+
+ // Data
+ using _data_t = with_data_t;
+
+ // Member implementation with data and methods
+ template
+ struct _impl_t
+ {
+ public:
+ _data_t _data;
+ };
+
+ // Base template to be inherited by the statement
+ template
+ struct _base_t
+ {
+ using _data_t = with_data_t;
+
+ _impl_t where;
+ _impl_t& operator()() { return where; }
+ const _impl_t& operator()() const { return where; }
+
+ template
+ static auto _get_member(T t) -> decltype(t.where)
+ {
+ return t.where;
+ }
+
+#warning: Need real checks here
+ using _consistency_check = consistent_t;
+ };
+ };
+
+
+ struct no_with_t
+ {
+ using _traits = make_traits;
+ using _recursive_traits = make_recursive_traits<>;
+
+ // Data
+ using _data_t = no_data_t;
+
+ // Member implementation with data and methods
+ template
+ struct _impl_t
+ {
+ _data_t _data;
+ };
+
+ // Base template to be inherited by the statement
+ template
+ struct _base_t
+ {
+ using _data_t = no_data_t;
+
+ _impl_t no_with;
+ _impl_t& operator()() { return no_with; }
+ const _impl_t& operator()() const { return no_with; }
+
+ template
+ static auto _get_member(T t) -> decltype(t.no_with)
+ {
+ return t.no_with;
+ }
+
+ using _consistency_check = consistent_t;
+
+ };
+ };
+
+ template
+ struct blank_with_t
+ {
+ with_data_t _data;
+
+ template
+ auto operator()(Statement statement)
+ -> new_statement_t>
+ {
+ // FIXME need checks here, e.g. if there is recursion
+ return { statement, _data };
+ }
+ };
+
+ template
+ auto with(Expressions... cte)
+ -> blank_with_t
+ {
+ return { {cte...} };
+ }
+}
+
+#endif
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index f3127acf..74505083 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -19,6 +19,7 @@ endmacro ()
#build_and_run(Minimalistic)
#build_and_run(ResultTest)
build_and_run(UnionTest)
+build_and_run(WithTest)
# if you want to use the generator, you can do something like this:
#find_package(PythonInterp REQUIRED)
diff --git a/tests/WithTest.cpp b/tests/WithTest.cpp
new file mode 100644
index 00000000..6932966e
--- /dev/null
+++ b/tests/WithTest.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013-2014, 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 "Sample.h"
+#include "MockDb.h"
+#include
+#include
+#include
+
+MockDb db;
+MockDb::_serializer_context_t printer;
+
+int main()
+{
+ // to be done
+
+ return 0;
+}