From 705f39e37975d1c3a6ced1d15616ab2019e6cf39 Mon Sep 17 00:00:00 2001 From: Roland Bock Date: Tue, 13 Aug 2013 22:43:10 +0200 Subject: [PATCH] Initial commit --- LICENSE | 4 +- README.md | 82 +++++++ alias.h | 110 +++++++++ assignment_list.h | 67 +++++ boolean.h | 148 +++++++++++ column.h | 77 ++++++ column_fwd.h | 37 +++ column_types.h | 34 +++ connection.h | 36 +++ database/api.h | 103 ++++++++ detail/basic_operators.h | 176 +++++++++++++ detail/make_expression_tuple.h | 66 +++++ detail/make_flag_tuple.h | 70 ++++++ detail/serialize_tuple.h | 73 ++++++ detail/set.h | 214 ++++++++++++++++ detail/tag.h | 40 +++ detail/wrap_operand.h | 123 ++++++++++ detail/wrong.h | 42 ++++ examples/InsertTest.cpp | 54 ++++ examples/RemoveTest.cpp | 55 +++++ examples/SelectTest.cpp | 282 +++++++++++++++++++++ examples/TabSample.h | 179 ++++++++++++++ examples/UpdateTest.cpp | 55 +++++ examples/compile.sh | 3 + exception.h | 43 ++++ expression.h | 281 +++++++++++++++++++++ expression_fwd.h | 39 +++ from.h | 59 +++++ functions.h | 166 +++++++++++++ group_by.h | 68 +++++ having.h | 54 ++++ insert.h | 114 +++++++++ join.h | 100 ++++++++ limit.h | 64 +++++ multi_column.h | 81 ++++++ no_value.h | 47 ++++ noop.h | 45 ++++ noop_fwd.h | 37 +++ numeric.h | 185 ++++++++++++++ order_by.h | 64 +++++ raw_result_row.h | 44 ++++ remove.h | 122 +++++++++ result.h | 116 +++++++++ result_row.h | 119 +++++++++ select.h | 437 +++++++++++++++++++++++++++++++++ select_expression_list.h | 113 +++++++++ select_flag_list.h | 110 +++++++++ select_fwd.h | 70 ++++++ select_pseudo_table.h | 123 ++++++++++ sort_order.h | 62 +++++ table_base.h | 113 +++++++++ text.h | 138 +++++++++++ transaction.h | 96 ++++++++ type_traits.h | 117 +++++++++ update.h | 122 +++++++++ using.h | 54 ++++ where.h | 56 +++++ 57 files changed, 5587 insertions(+), 2 deletions(-) create mode 100644 alias.h create mode 100644 assignment_list.h create mode 100644 boolean.h create mode 100644 column.h create mode 100644 column_fwd.h create mode 100644 column_types.h create mode 100644 connection.h create mode 100644 database/api.h create mode 100644 detail/basic_operators.h create mode 100644 detail/make_expression_tuple.h create mode 100644 detail/make_flag_tuple.h create mode 100644 detail/serialize_tuple.h create mode 100644 detail/set.h create mode 100644 detail/tag.h create mode 100644 detail/wrap_operand.h create mode 100644 detail/wrong.h create mode 100644 examples/InsertTest.cpp create mode 100644 examples/RemoveTest.cpp create mode 100644 examples/SelectTest.cpp create mode 100644 examples/TabSample.h create mode 100644 examples/UpdateTest.cpp create mode 100644 examples/compile.sh create mode 100644 exception.h create mode 100644 expression.h create mode 100644 expression_fwd.h create mode 100644 from.h create mode 100644 functions.h create mode 100644 group_by.h create mode 100644 having.h create mode 100644 insert.h create mode 100644 join.h create mode 100644 limit.h create mode 100644 multi_column.h create mode 100644 no_value.h create mode 100644 noop.h create mode 100644 noop_fwd.h create mode 100644 numeric.h create mode 100644 order_by.h create mode 100644 raw_result_row.h create mode 100644 remove.h create mode 100644 result.h create mode 100644 result_row.h create mode 100644 select.h create mode 100644 select_expression_list.h create mode 100644 select_flag_list.h create mode 100644 select_fwd.h create mode 100644 select_pseudo_table.h create mode 100644 sort_order.h create mode 100644 table_base.h create mode 100644 text.h create mode 100644 transaction.h create mode 100644 type_traits.h create mode 100644 update.h create mode 100644 using.h create mode 100644 where.h diff --git a/LICENSE b/LICENSE index 64e4d18a..c53feede 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2013, rbock +Copyright (c) 2013, Roland Bock All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -20,4 +20,4 @@ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 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. \ No newline at end of file +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index ac7b6e46..4c265ef9 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,85 @@ sqlpp11 ======= A type safe SQL template library for C++ + + +Motivation: +----------- +SQL and C++ are both strongly typed languages. They should play well together. Still, most C/C++ interface are based on constructing strings for querys and on interpreting arrays or maps of strings as results. Typicaly there are a bunch of helper functions and classes that help to construct queries, to interpret results or to avoid code injection. + +sqlpp11 is a templated library representing an embedded domain specific language (EDSL) that allows you to + + * define types representing tables and columns + * construct typesafe queries checked at compile time for syntax errors, type errors, name errors and even some semantic errors + * interpret results by iterating over query-specific structs with appropriately named and typed members + +Under the hood, it still communicates with the database via strings, but the library user operates on structs and functions. And the compiler will report many kinds of errors long before the code enters unit testing or production. + +Examples: +--------- +For the examples, lets assume you had a table class representing something like + +```SQL +CREATE TABLE foo ( + id bigint, + name varchar(50), + hasFun bool +); +``` + +And we assume to have a database connection object: + +```C++ +TabFoo foo; +Db db(/* some arguments*/); + +// selecting zero or more results, iterating over the results +for (const auto& row: db.run(select(foo.name, foo.hasFun).from(foo).where(foo.id > 17 and foo.name.like("%bar%")))) +{ + if (row.name.is_null()) + std::cerr << "name is null, will convert to empty string" << std::endl; + std::string name = row.name; // string-like fields are implicitly convertible to string + bool hasFun = hasFun; // bool fields are implicitly convertible to bool +} + +// selecting ALL columns of a table +for (const auto& row: db.run(select(all_of(foo)).from(foo).where(hasFun or foo.name == "joker"))) +{ + int64_t id = row.id; // numeric fields are implicitly convertible to numeric c++ types +} + +// selecting zero or one row, showing off with an alias: +SQLPP_ALIAS_PROVIDER_GENERATOR(cheese); +if (const auto& row = db.run(select(foo.name.as(cheese)).from(foo).where(foo.id == 17))) +{ + std::cerr << "found: " << row.cheese << std::endl; +} + +// selecting exactly one row: +return db.run(select(count(foo.id)).from(foo))->count; + +Of course there are joins and subqueries, more functions, order_by, group_by etc. +These will be documented soon. + +// A sample insert +db.run(insert_into(foo).set(foo.id = 17, foo.name = "bar", foo.hasFun = true)); + +// A sample update +db.run(update(foo).set(foo.hasFun = not foo.hasFun).where(foo.name != "nobody"); + +// A sample delete +db.run(remove_from(tab).where(not tab.hasFun)); +``` + +Requirements: +------------- +sqlpp11 makes heavy use of C++11. It has been developed using + +clang-3.2 on Ubuntu-10.4 with matching libc++ + +It also requires a database library with a matching interface, see database/api.h + +Links to sample implementations will follow soon. + + + diff --git a/alias.h b/alias.h new file mode 100644 index 00000000..70afa75c --- /dev/null +++ b/alias.h @@ -0,0 +1,110 @@ +/* + * 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_ALIAS_H +#define SQLPP_ALIAS_H + +#include +namespace sqlpp +{ + namespace alias + { +#define SQLPP_ALIAS_PROVIDER_GENERATOR(name) \ + struct name##_t\ + {\ + struct _name_t\ + {\ + static constexpr const char* _get_name() { return #name; }\ + };\ + template\ + struct _member_t\ + {\ + template\ + _member_t(TT&&... t): name(std::forward(t)...) {}\ + \ + template\ + _member_t& operator=(TT&& t) { name = std::forward(t); return *this; }\ + \ + T name;\ + };\ + };\ + constexpr name##_t name = {}; + + SQLPP_ALIAS_PROVIDER_GENERATOR(a); + SQLPP_ALIAS_PROVIDER_GENERATOR(b); + SQLPP_ALIAS_PROVIDER_GENERATOR(c); + SQLPP_ALIAS_PROVIDER_GENERATOR(d); + SQLPP_ALIAS_PROVIDER_GENERATOR(e); + SQLPP_ALIAS_PROVIDER_GENERATOR(f); + SQLPP_ALIAS_PROVIDER_GENERATOR(g); + SQLPP_ALIAS_PROVIDER_GENERATOR(h); + SQLPP_ALIAS_PROVIDER_GENERATOR(i); + SQLPP_ALIAS_PROVIDER_GENERATOR(j); + SQLPP_ALIAS_PROVIDER_GENERATOR(k); + SQLPP_ALIAS_PROVIDER_GENERATOR(l); + SQLPP_ALIAS_PROVIDER_GENERATOR(m); + SQLPP_ALIAS_PROVIDER_GENERATOR(n); + SQLPP_ALIAS_PROVIDER_GENERATOR(o); + SQLPP_ALIAS_PROVIDER_GENERATOR(p); + SQLPP_ALIAS_PROVIDER_GENERATOR(q); + SQLPP_ALIAS_PROVIDER_GENERATOR(s); + SQLPP_ALIAS_PROVIDER_GENERATOR(t); + SQLPP_ALIAS_PROVIDER_GENERATOR(u); + SQLPP_ALIAS_PROVIDER_GENERATOR(v); + SQLPP_ALIAS_PROVIDER_GENERATOR(w); + SQLPP_ALIAS_PROVIDER_GENERATOR(x); + SQLPP_ALIAS_PROVIDER_GENERATOR(y); + SQLPP_ALIAS_PROVIDER_GENERATOR(z); + SQLPP_ALIAS_PROVIDER_GENERATOR(left); + SQLPP_ALIAS_PROVIDER_GENERATOR(right); + }; + + template + struct expression_alias_t + { + struct _value_type: Expression::_value_type + { + using _is_expression = tag_no; + using _is_named_expression = tag_yes; + using _is_alias = tag_yes; + }; + + using _name_t = typename AliasProvider::_name_t; + template + using _member_t = typename AliasProvider::template _member_t; + + template + void serialize(std::ostream& os, Db& db) const + { + os << "("; _expression.serialize(os, db); os << ") AS " << _name_t::_get_name(); + } + + Expression _expression; + }; + +} + +#endif diff --git a/assignment_list.h b/assignment_list.h new file mode 100644 index 00000000..bb5024b7 --- /dev/null +++ b/assignment_list.h @@ -0,0 +1,67 @@ +/* + * 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_ASSIGNMENT_LIST_H +#define SQLPP_ASSIGNMENT_LIST_H + +#include +#include +#include + +namespace sqlpp +{ + template class ProhibitPredicate, typename... Assignment> + struct assignment_list_t + { + // check for at least one order expression + static_assert(sizeof...(Assignment), "at least one select expression required in set()"); + + // check for duplicate assignments + static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in set()"); + + // check for invalid assignments + using _assignment_set = typename detail::make_set_if::type; + static_assert(_assignment_set::size::value == sizeof...(Assignment), "at least one argument is not an assignment in set()"); + + // check for prohibited assignments + using _prohibited_assignment_set = typename detail::make_set_if::type; + static_assert(_prohibited_assignment_set::size::value == 0, "at least one assignment is prohibited by its column definition in set()"); + + using _is_assignment_list = tag_yes; + + template + void serialize(std::ostream& os, Db& db) const + { + os << " SET "; + detail::serialize_tuple(os, db, _assignments, ','); + } + + std::tuple _assignments; + }; + +} + +#endif diff --git a/boolean.h b/boolean.h new file mode 100644 index 00000000..a1a36947 --- /dev/null +++ b/boolean.h @@ -0,0 +1,148 @@ +/* + * 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_BOOLEAN_H +#define SQLPP_BOOLEAN_H + +#include +#include +#include +#include +#include + +namespace sqlpp +{ + // boolean operators + namespace detail + { + struct or_ + { + using _value_type = boolean; + static constexpr const char* _name = "OR"; + }; + + struct and_ + { + using _value_type = boolean; + static constexpr const char* _name = "AND"; + }; + + struct not_ + { + using _value_type = boolean; + static constexpr const char* _name = "NOT"; + }; + + // boolean value type + struct boolean + { + using _base_value_type = boolean; + using _is_boolean = tag_yes; + using _is_value = tag_yes; + using _is_expression = tag_yes; + + struct plus_ + { + using _value_type = boolean; + static constexpr const char* _name = "+"; + }; + + template + struct _result_entry_t + { + _result_entry_t(const raw_result_row_t& row): + _is_valid(row.data != nullptr), + _is_null(row.data == nullptr or row.data[index] == nullptr), + _value(_is_null ? false : (std::strtoll(row.data[index], nullptr, 10) != 0)) + {} + + _result_entry_t& operator=(const raw_result_row_t& row) + { + _is_valid = (row.data != nullptr); + _is_null = row.data == nullptr or row.data[index] == nullptr; + _value = _is_null ? false : (std::strtoll(row.data[index], nullptr, 10) != 0); + return *this; + } + + template + void serialize(std::ostream& os, Db& db) const + { + os << value(); + } + + bool _is_trivial() const { return value() == false; } + + bool is_null() const { return _is_null; } + bool value() const + { + if (not _is_valid) + throw exception("accessing value in non-existing row"); + return _value; + } + operator bool() const { return value(); } + + private: + bool _is_valid; + bool _is_null; + bool _value; + }; + + template + using _constraint = operand_t; + + template + struct operators: public basic_operators + { + template + nary_expression_t::type> operator and(T&& t) const + { + return { *static_cast(this), std::forward(t) }; + } + + template + nary_expression_t::type> operator or(T&& t) const + { + return { *static_cast(this), std::forward(t) }; + } + + not_t operator not() const + { + return { *static_cast(this) }; + } + }; + }; + + template + std::ostream& operator<<(std::ostream& os, const boolean::_result_entry_t& e) + { + return os << e.value(); + } + } + + using boolean = detail::boolean; + +} +#endif diff --git a/column.h b/column.h new file mode 100644 index 00000000..94526614 --- /dev/null +++ b/column.h @@ -0,0 +1,77 @@ +/* + * 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_COLUMN_H +#define SQLPP_COLUMN_H + +#include +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + template + struct column_t: public ColumnSpec::_value_type::template operators> + { + using _table = Table; + using _column_type = typename ColumnSpec::_column_type; + struct _value_type: ColumnSpec::_value_type + { + using _is_expression = tag_yes; + using _is_named_expression = tag_yes; + using _is_alias = tag_no; + }; + + using _name_t = typename ColumnSpec::_name_t; + template + using _member_t = typename ColumnSpec::template _member_t; + + template + void serialize(std::ostream& os, Db& db) const + { + os << Table::_name_t::_get_name() << '.' << _name_t::_get_name(); + } + + template + expression_alias_t::type> as(alias_provider&&) const + { + return { *this }; + } + + template + assignment_t::type> operator =(T&& t) const + { + return { *this, std::forward(t) }; + } + }; + +} + +#endif diff --git a/column_fwd.h b/column_fwd.h new file mode 100644 index 00000000..e655bad5 --- /dev/null +++ b/column_fwd.h @@ -0,0 +1,37 @@ +/* + * 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_COLUMN_FWD_H +#define SQLPP_COLUMN_FWD_H + +namespace sqlpp +{ + template + class column_t; +} + +#endif diff --git a/column_types.h b/column_types.h new file mode 100644 index 00000000..87943d5c --- /dev/null +++ b/column_types.h @@ -0,0 +1,34 @@ +/* + * 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_COLUMN_TYPES_H +#define SQLPP_COLUMN_TYPES_H + +#include +#include +#include + +#endif diff --git a/connection.h b/connection.h new file mode 100644 index 00000000..13cd6c69 --- /dev/null +++ b/connection.h @@ -0,0 +1,36 @@ +/* + * 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_CONNECTION_H +#define SQLPP_CONNECTION_H + +namespace sqlpp +{ + struct connection {}; +} + +#endif + diff --git a/database/api.h b/database/api.h new file mode 100644 index 00000000..fecb1ccb --- /dev/null +++ b/database/api.h @@ -0,0 +1,103 @@ +/* + * 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_DATABASE_API_H +#define SQLPP_DATABASE_API_H + +#include +#include +#include + +namespace sqlpp +{ + class result + { + public: + result() = default; + result(const result&) = delete; + result(result&& rhs) = default; + result& operator=(const result&) = delete; + result& operator=(result&&) = default; + ~result() = default; + + bool operator==(const result& rhs) const; + + //! return the next row from the result or nullptr, if there is no next row + sqlpp::raw_result_row_t next(); + size_t num_cols() const; + size_t num_rows() const; + }; + + class connection: public sqlpp::connection + { + public: + connection(/*whatever arguments you need*/); + connection(const connection&) = delete; + connection(connection&&) = delete; + connection& operator=(const connection&) = delete; + connection& operator=(connection&&) = delete; + ~connection(); + + //! select returns a result (which can be iterated row by row) + result select(const std::string& query); + + //! insert returns the last auto_incremented id (or zero, if there is none) + size_t insert(const std::string& query); + + //! update returns the number of affected rows + size_t update(const std::string& query); + + //! remove returns the number of removed rows + size_t remove(const std::string& query); + + //! execute arbitrary command (e.g. create a table) + void execute(const std::string& command); + + //! escape given string + std::string escape(const std::string& s) const; + + //! call run on the argument + template + auto run(const T& t) -> decltype(t.run(*this)) + { + return t.run(*this); + } + + //! start transaction + void start_transaction(); + + //! commit transaction (or throw transaction if the transaction has been finished already) + void commit_transaction(); + + //! rollback transaction with or without reporting the rollback (or throw if the transaction has been finished already) + void rollback_transaction(bool report); + + //! report a rollback failure (will be called by transactions in case of a rollback failure in the destructor) + void report_rollback_failure(const std::string message) noexcept; + }; + } +} +#endif diff --git a/detail/basic_operators.h b/detail/basic_operators.h new file mode 100644 index 00000000..02a2a3ae --- /dev/null +++ b/detail/basic_operators.h @@ -0,0 +1,176 @@ +/* + * 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_DETAIL_BASIC_OPERATORS_H +#define SQLPP_DETAIL_BASIC_OPERATORS_H + +#include +#include +#include + +namespace sqlpp +{ + + namespace detail + { + struct boolean; + + // operators + struct lt_ + { + using _value_type = boolean; + static constexpr const char* _name = "<"; + }; + + struct le_ + { + using _value_type = boolean; + static constexpr const char* _name = "<="; + }; + + struct ge_ + { + using _value_type = boolean; + static constexpr const char* _name = ">="; + }; + + struct gt_ + { + using _value_type = boolean; + static constexpr const char* _name = ">"; + }; + + struct is_null_ + { + using _value_type = boolean; + static constexpr const char* _name = "IS NULL"; + }; + + struct is_not_null_ + { + using _value_type = boolean; + static constexpr const char* _name = "IS NOT NULL"; + }; + + struct in_ + { + using _value_type = boolean; + static constexpr const char* _name = "IN"; + }; + + struct not_in_ + { + using _value_type = boolean; + static constexpr const char* _name = "NOT IN"; + }; + + + // basic operators + template class Constraint> + struct basic_operators + { + template + equal_t::type> operator==(T&& t) const + { + return { *static_cast(this), std::forward(t) }; + } + + template + not_equal_t::type> operator!=(T&& t) const + { + return { *static_cast(this), std::forward(t) }; + } + template + nary_expression_t::type> operator<(T&& t) const + { + return { *static_cast(this), std::forward(t) }; + } + + template + nary_expression_t::type> operator<=(T&& t) const + { + return { *static_cast(this), std::forward(t) }; + } + + template + nary_expression_t::type> operator>=(T&& t) const + { + return { *static_cast(this), std::forward(t) }; + } + + template + nary_expression_t::type> operator>(T&& t) const + { + return { *static_cast(this), std::forward(t) }; + } + + nary_expression_t is_null() const + { + return { *static_cast(this) }; + } + + nary_expression_t is_not_null() const + { + return { *static_cast(this) }; + } + + sort_order_t asc() + { + return { *static_cast(this) }; + } + + sort_order_t desc() + { + return { *static_cast(this) }; + } + + // Hint: use wrappers for containers... + template + nary_expression_t::type...> in(T&&... t) const + { + static_assert(sizeof...(T) > 0, "in() requires at least one argument"); + return { *static_cast(this), std::forward(t)... }; + } + + template + nary_expression_t::type...> not_in(T&&... t) const + { + static_assert(sizeof...(T) > 0, "not_in() requires at least one argument"); + return { *static_cast(this), std::forward(t)... }; + } + + template + expression_alias_t::type> as(alias_provider&&) + { + return { *static_cast(this) }; + } + + constexpr bool _is_trivial() const { return false; } + }; + } + +} +#endif diff --git a/detail/make_expression_tuple.h b/detail/make_expression_tuple.h new file mode 100644 index 00000000..759209ac --- /dev/null +++ b/detail/make_expression_tuple.h @@ -0,0 +1,66 @@ +/* + * 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_DETAIL_MAKE_EXPRESSION_TUPLE_H +#define SQLPP_DETAIL_MAKE_EXPRESSION_TUPLE_H + +namespace sqlpp +{ + namespace detail + { + template + auto make_single_expression_tuple(Expr&& expr) -> typename std::enable_if::type>::value, decltype(std::make_tuple(expr))>::type + { + return std::make_tuple(std::forward(expr)); + }; + + template + auto make_single_expression_tuple(Expr&& expr) -> typename std::enable_if::type>::value, std::tuple<>>::type + { + return {}; + }; + + template + auto make_single_expression_tuple(Tab&& tab) -> typename std::enable_if::type>::value, typename std::decay::type::_all_of_t>::type + { + return {}; + }; + + template + auto make_single_expression_tuple(std::tuple&& t) -> std::tuple + { + return t; + }; + + template + auto make_expression_tuple(Expr&&... expr) -> decltype(std::tuple_cat(make_single_expression_tuple(std::forward(expr))...)) + { + return std::tuple_cat(make_single_expression_tuple(std::forward(expr))...); + }; + + } +} +#endif diff --git a/detail/make_flag_tuple.h b/detail/make_flag_tuple.h new file mode 100644 index 00000000..dc73a4d8 --- /dev/null +++ b/detail/make_flag_tuple.h @@ -0,0 +1,70 @@ +/* + * 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_DETAIL_MAKE_FLAG_TUPLE_H +#define SQLPP_DETAIL_MAKE_FLAG_TUPLE_H + +namespace sqlpp +{ + namespace detail + { + // accept select flags + template + auto make_single_flag_tuple(Expr&& expr) -> typename std::enable_if::type>::value, decltype(std::make_tuple(expr))>::type + { + return std::make_tuple(std::forward(expr)); + }; + + // ignore named expressions + template + auto make_single_flag_tuple(Expr&& expr) -> typename std::enable_if::type>::value, std::tuple<>>::type + { + return {}; + }; + + // ignore tables + template + auto make_single_flag_tuple(Tab&& tab) -> typename std::enable_if::type>::value, std::tuple<>>::type + { + return {}; + }; + + // ignore tuples of expressions + template + auto make_single_flag_tuple(std::tuple&& t) -> std::tuple<> + { + return {}; + }; + + template + auto make_flag_tuple(Expr&&... expr) -> decltype(std::tuple_cat(make_single_flag_tuple(std::forward(expr))...)) + { + return std::tuple_cat(make_single_flag_tuple(std::forward(expr))...); + }; + + } +} +#endif diff --git a/detail/serialize_tuple.h b/detail/serialize_tuple.h new file mode 100644 index 00000000..25c33698 --- /dev/null +++ b/detail/serialize_tuple.h @@ -0,0 +1,73 @@ +/* + * 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_DETAIL_SERIALIZE_TUPLE_H +#define SQLPP_DETAIL_SERIALIZE_TUPLE_H + +#include +#include +#include + +namespace sqlpp +{ + namespace detail + { + template + struct tuple_serializer_impl + { + template + static void serialize(std::ostream& os, Db& db, const Tuple& flags_and_columns, char separator) + { + if (index > begin) + os << separator; + const auto& entry = std::get(flags_and_columns); + using entry_type = typename std::tuple_element::type; + if (requires_braces_t::value) + os << "("; + entry.serialize(os, db); + if (requires_braces_t::value) + os << ")"; + tuple_serializer_impl::serialize(os, db, flags_and_columns, separator); + } + }; + template + struct tuple_serializer_impl + { + template + static void serialize(std::ostream& os, Db& db, const Tuple& flags_and_columns, char separator) + { + } + }; + + template + static void serialize_tuple(std::ostream& os, Db& db, const Tuple& flags_and_columns, char separator) + { + tuple_serializer_impl<0, 0, std::tuple_size::value>::serialize(os, db, flags_and_columns, separator); + } + } +} + +#endif diff --git a/detail/set.h b/detail/set.h new file mode 100644 index 00000000..e2166142 --- /dev/null +++ b/detail/set.h @@ -0,0 +1,214 @@ +/* + * 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_DETAIL_SET_H +#define SQLPP_DETAIL_SET_H + +#include +#include + +namespace sqlpp +{ + namespace detail + { + template + struct make_set; + + template + class empty {}; + + template + struct is_superset_of_impl + : std::false_type {}; + + template + struct is_superset_of_impl + : std::true_type {}; + + template + struct is_superset_of_impl + : std::integral_constant::value and is_superset_of_impl::value> {}; + + template + struct is_disjunct_from_impl + : std::false_type {}; + + template + struct is_disjunct_from_impl + : std::true_type {}; + + template + struct is_disjunct_from_impl + : std::integral_constant::value and is_disjunct_from_impl::value> {}; + + template + struct set: empty... + { + struct size: std::integral_constant {}; + + template + struct contains + : std::integral_constant, set>::value> {}; + + template + struct is_superset_of + { + static_assert(wrong::value, "invalid argument for is_superset_of"); + }; + + template + struct is_superset_of> + : is_superset_of_impl{}; + + template + struct join + { + static_assert(wrong::value, "invalid argument for set::join"); + }; + + template + struct join> + : make_set {}; + + template + struct is_disjunct_from + { + static_assert(wrong::value, "invalid argument for is_disjunct_from"); + }; + + template + struct is_disjunct_from> + : is_disjunct_from_impl{}; + + template + struct is_subset_of + { + static_assert(wrong::value, "invalid argument for is_subset_of"); + }; + + template + struct is_subset_of> + : is_superset_of_impl, Element...>{}; + + template + struct equals + { + static_assert(wrong::value, "invalid argument for equals"); + }; + + template + struct equals> + : std::integral_constant, Element...>::value + and + is_superset_of_impl, T...>::value> {}; + + template + struct insert + { + typedef set type; + }; + + template + struct insert::value>::type> + { + typedef set type; + }; + + template class Predicate, typename T, typename Enable = void> + struct insert_if + { + typedef set type; + }; + + template class Predicate, typename T> + struct insert_if::value and Predicate::value>::type> + { + typedef set type; + }; + + }; + + template<> + struct make_set<> + { + typedef set<> type; + }; + + template + struct make_set + { + typedef typename make_set::type::template insert::type type; + }; + + template class Predicate, typename... T> + struct make_set_if; + + template class Predicate> + struct make_set_if + { + typedef set<> type; + }; + + template class Predicate, typename T, typename... Rest> + struct make_set_if + { + typedef typename make_set_if::type::template insert_if::type type; + }; + + template class Predicate, typename... T> + struct make_set_if_not + { + template + struct InversePredicate + { + static constexpr bool value = Predicate::value; + }; + using type = typename make_set_if::type; + }; + + template + struct has_duplicates + : std::integral_constant::type::size::value != sizeof...(T)> {}; + +#if WANT_AUTO_JOIN + template + struct begin // FIXME: Should move this into set struct + { + static_assert(wrong::value, "begin template used on invalid type container"); + }; + + template + struct begin> + { + using type = T; + }; +#endif // WANT_AUTO_JOIN + } +} + + +#endif diff --git a/detail/tag.h b/detail/tag.h new file mode 100644 index 00000000..ca7f12da --- /dev/null +++ b/detail/tag.h @@ -0,0 +1,40 @@ +/* + * 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_DETAIL_TAG_H +#define SQLPP_DETAIL_TAG_H + +namespace sqlpp +{ + namespace detail + { + struct tag {}; + } + using tag_yes = detail::tag; + using tag_no = void; +} + +#endif diff --git a/detail/wrap_operand.h b/detail/wrap_operand.h new file mode 100644 index 00000000..4546aab8 --- /dev/null +++ b/detail/wrap_operand.h @@ -0,0 +1,123 @@ +/* + * 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_DETAIL_WRAP_OPERAND_H +#define SQLPP_DETAIL_WRAP_OPERAND_H + +#include +#include + +namespace sqlpp +{ + namespace detail + { + struct boolean; + struct numeric; + struct text; + + struct bool_operand + { + static constexpr bool _is_expression = true; + using _value_type = boolean; + + bool_operand(bool t): _t(t) {} + + template + void serialize(std::ostream& os, Db& db) const + { + os << _t; + } + + bool _is_trivial() const { return _t == false; } + + const bool _t; + }; + + template + struct numeric_operand + { + static constexpr bool _is_expression = true; + using _value_type = numeric; + + numeric_operand(T t): _t(t) {} + + template + void serialize(std::ostream& os, Db& db) const + { + os << _t; + } + + bool _is_trivial() const { return _t == 0; } + + const T _t; + }; + + template + struct text_operand + { + static constexpr bool _is_expression = true; + using _value_type = text; + + text_operand(const T& t): _t(t) {} + + template + void serialize(std::ostream& os, Db& db) const + { + os << '"' << db.escape(_t) << '"'; + } + + bool _is_trivial() const { return _t.empty(); } + + const std::string _t; + }; + + template + struct wrap_operand + { + using type = T; + }; + + template<> + struct wrap_operand + { + using type = bool_operand; + }; + + template + struct wrap_operand::value>::type> + { + using type = numeric_operand; + }; + + template + struct wrap_operand::value>::type> + { + using type = text_operand; + }; + } +} + +#endif diff --git a/detail/wrong.h b/detail/wrong.h new file mode 100644 index 00000000..110ba2c9 --- /dev/null +++ b/detail/wrong.h @@ -0,0 +1,42 @@ +/* + * 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_DETAIL_WRONG_H +#define SQLPP_DETAIL_WRONG_H + +#include + +namespace sqlpp +{ + namespace detail + { + // A template that always returns false + // To be used with static assert, for instance, to ensure it + // fires only when the template is instantiated. + template struct wrong : std::false_type {}; + } +} +#endif diff --git a/examples/InsertTest.cpp b/examples/InsertTest.cpp new file mode 100644 index 00000000..c5f77987 --- /dev/null +++ b/examples/InsertTest.cpp @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +#include +class DbMock +{ +public: + const std::string& escape(const std::string& text) { return text; } +}; + +DbMock db; + +int main() +{ + TabSample t; + + auto x = t.alpha = 7; + auto y = t.beta = "kaesekuchen"; + auto z = t.gamma = true; + + insert_into(t).serialize(std::cerr, db); std::cerr << "\n"; + insert_into(t).set(t.beta = "kirschauflauf").serialize(std::cerr, db); std::cerr << "\n"; + //insert_into(t).values(7, "wurstwaren", true).serialize(std::cerr, db); std::cerr << "\n"; + //insert_into(t).columns(t.alpha, t.beta).values(25, "drei").serialize(std::cerr, db); std::cerr << "\n"; + //insert_into(t).columns(t.alpha, t.beta).select(select(t.alpha, t.beta).from(t)).serialize(std::cerr, db); + return 0; +} diff --git a/examples/RemoveTest.cpp b/examples/RemoveTest.cpp new file mode 100644 index 00000000..530fa331 --- /dev/null +++ b/examples/RemoveTest.cpp @@ -0,0 +1,55 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +#include +class DbMock +{ +public: + const std::string& escape(const std::string& text) { return text; } +}; + +DbMock db; + +int main() +{ + TabSample t; + + auto x = t.alpha = 7; + auto y = t.beta = "kaesekuchen"; + auto z = t.gamma = true; + + remove_from(t).serialize(std::cerr, db); std::cerr << "\n"; + remove_from(t).where(t.beta != "transparent").serialize(std::cerr, db); std::cerr << "\n"; + remove_from(t).using_(t).serialize(std::cerr, db); std::cerr << "\n"; + //insert_into(t).values(7, "wurstwaren", true).serialize(std::cerr, db); std::cerr << "\n"; + //insert_into(t).columns(t.alpha, t.beta).values(25, "drei").serialize(std::cerr, db); std::cerr << "\n"; + //insert_into(t).columns(t.alpha, t.beta).select(select(t.alpha, t.beta).from(t)).serialize(std::cerr, db); + return 0; +} diff --git a/examples/SelectTest.cpp b/examples/SelectTest.cpp new file mode 100644 index 00000000..aa4f97cc --- /dev/null +++ b/examples/SelectTest.cpp @@ -0,0 +1,282 @@ +/* + * 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. + */ + +#include +#include + +#include +class DbMock +{ +public: + const std::string& escape(const std::string& text) { return text; } +}; + +DbMock db; + +int main() +{ + TabSample t; + + // Test a table + { + using T = decltype(t); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_expression_t::value, "type requirement"); + static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(sqlpp::is_table_t::value, "type requirement"); + } + + // Test an alias of table + { + using T = decltype(t.as(sqlpp::alias::a)); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_expression_t::value, "type requirement"); + static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(sqlpp::is_alias_t::value, "type requirement"); + static_assert(sqlpp::is_table_t::value, "type requirement"); + } + + // Test a colum of an alias of table + { + using T = decltype(t.as(sqlpp::alias::a).alpha); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + } + + + // Test a numeric table column + { + using T = decltype(t.alpha); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + } + // Test a an alias of a numeric table column + { + using T = decltype(t.alpha.as(sqlpp::alias::a)); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + } + + // Test a select of a single column without a from + { + using T = decltype(select(t.alpha)); // Hint: The current rule is pretty crude (a from is required), but certainly better than nothing + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_expression_t::value, "type requirement"); + static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + } + + // Test a select of a single numeric table column + { + using T = decltype(select(t.alpha).from(t)); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + } + + // Test a select of an alias of a single numeric table column + { + using T = decltype(select(t.alpha.as(sqlpp::alias::a)).from(t)); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + } + + // Test an alias of a select of a single numeric table column + { + using T = decltype(select(t.alpha).from(t).as(sqlpp::alias::b)); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_expression_t::value, "type requirement"); + static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "red to not be boolean"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(sqlpp::is_alias_t::value, "type requirement"); + static_assert(sqlpp::is_table_t::value, "type requirement"); + } + + // Test the column of an alias of a select of an alias of a single numeric table column + { + using T = decltype(select(t.alpha.as(sqlpp::alias::a)).from(t).as(sqlpp::alias::b)); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_expression_t::value, "type requirement"); + static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(sqlpp::is_alias_t::value, "type requirement"); + static_assert(sqlpp::is_table_t::value, "type requirement"); + } + + // Test the column of an alias of a select of a single numeric table column + { + using T = decltype(select(t.alpha).from(t).as(sqlpp::alias::b).alpha); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + } + + // Test an alias of a select of an alias of a single numeric table column + { + using T = decltype(select(t.alpha.as(sqlpp::alias::a)).from(t).as(sqlpp::alias::b).a); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + } + + // Test that select(all_of(tab)) is expanded in select + { + auto a = select(all_of(t)); + auto b = select(t.alpha, t.beta, t.gamma); + auto c = select(t); + static_assert(std::is_same::value, "all_of(t) has to be expanded by select()"); + static_assert(std::is_same::value, "t has to be expanded by select()"); + } + + // Test that select(all_of(tab)) is expanded in multi_column + { + auto a = multi_column(sqlpp::alias::a, all_of(t)); + auto b = multi_column(sqlpp::alias::a, t.alpha, t.beta, t.gamma); + static_assert(std::is_same::value, "all_of(t) has to be expanded by multi_column"); + } + + // Test that a multicolumn is not a value + { + auto m = multi_column(sqlpp::alias::a, t.alpha, t.beta); + auto a = select(m).from(t).as(sqlpp::alias::b).a; + static_assert(not sqlpp::is_value_t::value, "a multi_column is not a value"); + } + + + static_assert(sqlpp::is_select_flag_t::value, "sqlpp::all has to be a select_flag"); + using T = sqlpp::detail::wrap_operand::type; + static_assert(T::_is_expression, "T has to be an expression"); + static_assert(std::is_same::value, "T has to be a numeric"); + static_assert(sqlpp::is_numeric_t::value, "T has to be a numeric"); + static_assert(sqlpp::is_numeric_t::value, "TabSample.alpha has to be a numeric"); + ((t.alpha + 7) + 4).asc(); + static_assert(sqlpp::is_boolean_t::value, "Comparison expression have to be boolean"); + auto x = (t.gamma == true) and (t.alpha == 7); + auto y = t.gamma and true and t.gamma; + !t.gamma; + t.beta < "kaesekuchen"; + (t.beta + "hallenhalma").serialize(std::cerr, db); + static_assert(sqlpp::must_not_insert_t::value, "alpha must not be inserted"); + t.alpha.serialize(std::cerr, db); + std::cerr << "\n" << sizeof(TabSample) << std::endl; + static_assert(std::is_same::value, "alpha should be a named expression"); + static_assert(sqlpp::is_named_expression_t::value, "alpha should be a named expression"); + static_assert(sqlpp::is_named_expression_t::value, "an alias of alpha should be a named expression"); + static_assert(sqlpp::is_alias_t::value, "an alias of alpha should be an alias"); + auto z = select(t.alpha) == 7; + auto l = t.as(sqlpp::alias::left); + auto r = select(t.gamma.as(sqlpp::alias::a)).from(t).where(t.gamma == true).as(sqlpp::alias::right); + static_assert(sqlpp::is_boolean_t::value, "select(bool) has to be a bool"); + select(sqlpp::distinct, sqlpp::straight_join, l.alpha, l.beta, select(r.a).from(r)) + .from(l, r) + .where(t.beta == "hello world" and select(t.gamma).from(t))// .as(sqlpp::alias::right)) + .group_by(l.gamma, r.a) + .having(r.a != true) + .order_by(l.beta.asc()) + .limit(17) + .offset(3) + .as(sqlpp::alias::a) + .serialize(std::cerr, db); + + return 0; +} diff --git a/examples/TabSample.h b/examples/TabSample.h new file mode 100644 index 00000000..2e554771 --- /dev/null +++ b/examples/TabSample.h @@ -0,0 +1,179 @@ +/* + * 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_TAB_SAMPLE_H +#define SQLPP_TAB_SAMPLE_H + +#include +#include + + +namespace TabFoo_ +{ + struct Omega + { + struct _name_t + { + static constexpr const char* _get_name() { return "omega"; } + }; + template + struct _member_t + { + /* + template + _name_t(TT&&... t): omega(std::forward(t)...) {} + + template + _name_t& operator=(TT&& t) { omega = std::forward(t); return *this; } + */ + + T omega; + }; + using _value_type = sqlpp::bigint; + struct _column_type + { + }; + }; +} + +struct TabFoo: sqlpp::table_base_t< + TabFoo, + TabFoo_::Omega + > +{ + using _value_type = sqlpp::no_value_t; + struct _name_t + { + static constexpr const char* _get_name() { return "tab_foo"; } + }; + template + struct _member_t + { + T tabFoo; + }; + template + void serialize(std::ostream& os, Db& db) const + { + os << _name_t::_get_name(); + } +}; + +namespace TabSample_ +{ + struct Alpha + { + struct _name_t + { + static constexpr const char* _get_name() { return "alpha"; } + }; + template + struct _member_t + { + /* + template + _name_t(TT&&... t): alpha(std::forward(t)...) {} + + template + _name_t& operator=(TT&& t) { alpha = std::forward(t); return *this; } + */ + + T alpha; + }; + using _value_type = sqlpp::bigint; + struct _column_type + { + using _must_not_insert = sqlpp::tag_yes; + using _must_not_update = sqlpp::tag_yes; + using _can_be_null = sqlpp::tag_yes; + using _trivial_value_is_null = sqlpp::tag_yes; + using _foreign_key = decltype(TabFoo::omega); + }; + }; + + struct Beta + { + struct _name_t + { + static constexpr const char* _get_name() { return "beta"; } + }; + template + struct _member_t + { + T beta; + }; + using _value_type = sqlpp::varchar; + struct _column_type + { + using _can_be_null = sqlpp::tag_yes; + using _trivial_value_is_null = sqlpp::tag_yes; + using _must_not_update = sqlpp::tag_yes; + }; + }; + + struct Gamma + { + struct _name_t + { + static constexpr const char* _get_name() { return "gamma"; } + }; + template + struct _member_t + { + T gamma; + }; + using _value_type = sqlpp::boolean; + struct _column_type + { + using _require_insert = sqlpp::tag_yes; + }; + }; +} + +struct TabSample: sqlpp::table_base_t< + TabSample, + TabSample_::Alpha, + TabSample_::Beta, + TabSample_::Gamma + > +{ + using _value_type = sqlpp::no_value_t; + struct _name_t + { + static constexpr const char* _get_name() { return "tab_sample"; } + }; + template + struct _member_t + { + T tabSample; + }; + template + void serialize(std::ostream& os, Db& db) const + { + os << _name_t::_get_name(); + } +}; + +#endif diff --git a/examples/UpdateTest.cpp b/examples/UpdateTest.cpp new file mode 100644 index 00000000..cbe50f3a --- /dev/null +++ b/examples/UpdateTest.cpp @@ -0,0 +1,55 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +#include +class DbMock +{ +public: + const std::string& escape(const std::string& text) { return text; } +}; + +DbMock db; + +int main() +{ + TabSample t; + + auto x = t.alpha = 7; + auto y = t.beta = "kaesekuchen"; + auto z = t.gamma = true; + + update(t).serialize(std::cerr, db); std::cerr << "\n"; + update(t).set(t.gamma = false).serialize(std::cerr, db); std::cerr << "\n"; + update(t).set(t.gamma = false).where(t.beta != "transparent").serialize(std::cerr, db); std::cerr << "\n"; + //insert_into(t).values(7, "wurstwaren", true).serialize(std::cerr, db); std::cerr << "\n"; + //insert_into(t).columns(t.alpha, t.beta).values(25, "drei").serialize(std::cerr, db); std::cerr << "\n"; + //insert_into(t).columns(t.alpha, t.beta).select(select(t.alpha, t.beta).from(t)).serialize(std::cerr, db); + return 0; +} diff --git a/examples/compile.sh b/examples/compile.sh new file mode 100644 index 00000000..86dd4b2b --- /dev/null +++ b/examples/compile.sh @@ -0,0 +1,3 @@ +# to be called from the sqlpp11 folder +clang++ -std=c++11 -stdlib=libc++ examples/SelectTest.cpp -I.. + diff --git a/exception.h b/exception.h new file mode 100644 index 00000000..4cb938fd --- /dev/null +++ b/exception.h @@ -0,0 +1,43 @@ +/* + * 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_EXCEPTION_H +#define SQLPP_EXCEPTION_H + +#include + +namespace sqlpp +{ + class exception: public std::runtime_error + { + public: + exception(const std::string& what_arg): std::runtime_error(what_arg) {} + exception(const char* what_arg): std::runtime_error(what_arg) {} + }; +} + +#endif + diff --git a/expression.h b/expression.h new file mode 100644 index 00000000..7e2e947d --- /dev/null +++ b/expression.h @@ -0,0 +1,281 @@ +/* + * 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_EXPRESSION_H +#define SQLPP_EXPRESSION_H + +#include +#include +#include +#include + +namespace sqlpp +{ + template + struct assignment_t + { + using _is_assignment = tag_yes; + using column_type = Lhs; + + template + void serialize(std::ostream& os, Db& db) const + { + _lhs.serialize(os, db); + if (trivial_value_is_null_t::value and _rhs._is_trivial()) + { + os << "=NULL"; + } + else + { + os << "=("; + _rhs.serialize(os, db); + os << ")"; + } + } + + Lhs _lhs; + Rhs _rhs; + }; + + template + struct equal_t: public ValueType::template operators> + { + using _value_type = ValueType; + + template + equal_t(L&& l, R&& r): + _lhs(std::forward(l)), + _rhs(std::forward(r)) + {} + + equal_t(const equal_t&) = default; + equal_t(equal_t&&) = default; + equal_t& operator=(const equal_t&) = default; + equal_t& operator=(equal_t&&) = default; + ~equal_t() = default; + + template + void serialize(std::ostream& os, Db& db) const + { + _lhs.serialize(os, db); + if (trivial_value_is_null_t::value and _rhs._is_trivial()) + { + os << " IS NULL"; + } + else + { + os << "=("; + _rhs.serialize(os, db); + os << ")"; + } + } + + private: + Lhs _lhs; + Rhs _rhs; + }; + + template + struct not_equal_t: public ValueType::template operators> + { + using _value_type = ValueType; + + template + not_equal_t(L&& l, R&& r): + _lhs(std::forward(l)), + _rhs(std::forward(r)) + {} + + not_equal_t(const not_equal_t&) = default; + not_equal_t(not_equal_t&&) = default; + not_equal_t& operator=(const not_equal_t&) = default; + not_equal_t& operator=(not_equal_t&&) = default; + ~not_equal_t() = default; + + template + void serialize(std::ostream& os, Db& db) const + { + _lhs.serialize(os, db); + if (trivial_value_is_null_t::value and _rhs._is_trivial()) + { + os << " IS NOT NULL"; + } + else + { + os << "!=("; + _rhs.serialize(os, db); + os << ")"; + } + } + + private: + Lhs _lhs; + Rhs _rhs; + }; + + template + struct not_t: public ValueType::template operators> + { + using _value_type = ValueType; + + template + not_t(L&& l): + _lhs(std::forward(l)) + {} + + not_t(const not_t&) = default; + not_t(not_t&&) = default; + not_t& operator=(const not_t&) = default; + not_t& operator=(not_t&&) = default; + ~not_t() = default; + + template + void serialize(std::ostream& os, Db& db) const + { + if (trivial_value_is_null_t::value and _lhs._is_trivial()) + { + _lhs.serialize(os, db); + os << " IS NULL"; + } + else + { + os << "NOT("; + _lhs.serialize(os, db); + os << ")"; + } + } + + private: + Lhs _lhs; + }; + + template + struct nary_expression_t: public O::_value_type::template operators> + { + using _value_type = typename O::_value_type; + + nary_expression_t(Lhs&& l, Rhs&&... r): + _lhs(std::move(l)), + _rhs(std::move(r)...) + {} + + nary_expression_t(const Lhs& l, const Rhs&... r): + _lhs(l), + _rhs(r...) + {} + + nary_expression_t(const nary_expression_t&) = default; + nary_expression_t(nary_expression_t&&) = default; + nary_expression_t& operator=(const nary_expression_t&) = default; + nary_expression_t& operator=(nary_expression_t&&) = default; + ~nary_expression_t() = default; + + template + void serialize(std::ostream& os, Db& db) const + { + os << "("; + _lhs.serialize(os, db); + os << ")"; + os << O::_name; + os << "("; + detail::serialize_tuple(os, db, _rhs, ','); + os << ")"; + } + + private: + Lhs _lhs; + std::tuple _rhs; + }; + + template + struct nary_function_t: public F::_value_type::template operators> + { + using _value_type = typename F::_value_type; + + nary_function_t(Rhs&&... r): + _rhs(std::move(r)...) + {} + + nary_function_t(const Rhs&... r): + _rhs(r...) + {} + + nary_function_t(const nary_function_t&) = default; + nary_function_t(nary_function_t&&) = default; + nary_function_t& operator=(const nary_function_t&) = default; + nary_function_t& operator=(nary_function_t&&) = default; + ~nary_function_t() = default; + + template + void serialize(std::ostream& os, Db& db) const + { + os << F::_name; + os << "("; + detail::serialize_tuple(os, db, _rhs, ','); + os << ")"; + } + + private: + std::tuple _rhs; + }; + + template + struct named_nary_function_t: public F::_value_type::template operators> + { + using _value_type = typename F::_value_type; + using _name_t = typename F::_name_t; + template + using _member_t = typename F::template _member_t; + + named_nary_function_t(Rhs&&... r): + _rhs(std::move(r)...) + {} + + named_nary_function_t(const Rhs&... r): + _rhs(r...) + {} + + named_nary_function_t(const named_nary_function_t&) = default; + named_nary_function_t(named_nary_function_t&&) = default; + named_nary_function_t& operator=(const named_nary_function_t&) = default; + named_nary_function_t& operator=(named_nary_function_t&&) = default; + ~named_nary_function_t() = default; + + template + void serialize(std::ostream& os, Db& db) const + { + os << F::_name_t::_get_name(); + os << "("; + detail::serialize_tuple(os, db, _rhs, ','); + os << ")"; + } + + private: + std::tuple _rhs; + }; +} + +#endif diff --git a/expression_fwd.h b/expression_fwd.h new file mode 100644 index 00000000..e2c71b00 --- /dev/null +++ b/expression_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_EXPRESSION_FWD_H +#define SQLPP_EXPRESSION_FWD_H + +namespace sqlpp +{ + template + struct is_expression_t; + + template + struct is_named_expression_t; +} + +#endif diff --git a/from.h b/from.h new file mode 100644 index 00000000..59424074 --- /dev/null +++ b/from.h @@ -0,0 +1,59 @@ +/* + * 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_FROM_H +#define SQLPP_FROM_H + +#include +#include +#include +#include + +namespace sqlpp +{ + template + struct from_t + { + using _is_from = tag_yes; + + static_assert(sizeof...(TableOrJoin), "at least one table or join argument required in from"); + + //understand joins + //analyze tables and joins for duplicates + //produce a set of tables in this from + + template + void serialize(std::ostream& os, Db& db) const + { + os << " FROM "; + detail::serialize_tuple(os, db, _tables_and_joins, ','); + } + + std::tuple _tables_and_joins; + }; +} + +#endif diff --git a/functions.h b/functions.h new file mode 100644 index 00000000..1107b5b9 --- /dev/null +++ b/functions.h @@ -0,0 +1,166 @@ +/* + * 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_FUNCTIONS_H +#define SQLPP_FUNCTIONS_H + +#include +#include +#include + +namespace sqlpp +{ +#define SQLPP_MAKE_UNARY_TYPED_FUNCTION(NAME, SQL, CONSTRAINT, VALUE_TYPE) \ + namespace detail\ + {\ + template\ + struct NAME##_t\ + {\ + using _operand = typename operand_t::type;\ + \ + struct _op\ + {\ + struct _value_type: public VALUE_TYPE\ + {\ + using _is_named_expression = tag_yes;\ + };\ + struct _name_t\ + {\ + static constexpr const char* _get_name() { return #SQL; }\ + };\ + template\ + struct _member_t\ + {\ + M NAME;\ + };\ + };\ + \ + using type = named_nary_function_t<_op, _operand>;\ + };\ + }\ + template\ + auto NAME(T&& t) -> typename detail::NAME##_t::type\ + {\ + return { std::forward(t) };\ + } + +#define SQLPP_MAKE_UNARY_FUNCTION(NAME, SQL, CONSTRAINT) SQLPP_MAKE_UNARY_TYPED_FUNCTION(NAME, SQL, CONSTRAINT, _operand::_value_type) + + SQLPP_MAKE_UNARY_FUNCTION(avg, AVG, is_value_t); + SQLPP_MAKE_UNARY_FUNCTION(min, MIN, is_value_t); + SQLPP_MAKE_UNARY_FUNCTION(max, MAX, is_value_t); + SQLPP_MAKE_UNARY_FUNCTION(sum, SUM, is_value_t); + SQLPP_MAKE_UNARY_FUNCTION(any, ANY, is_select_t); + SQLPP_MAKE_UNARY_FUNCTION(some, SOME, is_select_t); + SQLPP_MAKE_UNARY_TYPED_FUNCTION(count, COUNT, is_expression_t, bigint); + SQLPP_MAKE_UNARY_TYPED_FUNCTION(exists, EXISTS, is_select_t, boolean); + SQLPP_MAKE_UNARY_TYPED_FUNCTION(not_exists, NOT EXISTS, is_select_t, boolean); + + template + auto value(T&& t) -> typename operand_t::type + { + static_assert(not is_value_t::type>::value, "value() is to be called with non-sqlpp-type like int, or string"); + return { std::forward(t) }; + } + + template + struct verbatim_t: public ValueType::template operators> + { + using _value_type = ValueType; + + template + void serialize(std::ostream& os, const Db& db) const + { + os << _verbatim; + } + + verbatim_t(const std::string& verbatim): _verbatim(verbatim) {} + verbatim_t(std::string&& verbatim): _verbatim(std::forward(verbatim)) {} + verbatim_t(const verbatim_t&) = default; + verbatim_t(verbatim_t&&) = default; + verbatim_t& operator=(const verbatim_t&) = default; + verbatim_t& operator=(verbatim_t&&) = default; + ~verbatim_t() = default; + + std::string _verbatim; + }; + + template + auto verbatim(StringType&& s) -> verbatim_t + { + return { std::forward(s) }; + } + + template + auto flatten(const Expression& exp, const Db& db) -> verbatim_t::type::_value_type::_base_value_type> + { + std::ostringstream os; + exp.serialize(os, db); + return { os.str() }; + } + + template + struct value_list_t // to be used in .in() method + { + using _container_t = Container; + using _value_type = typename operand_t::type::_value_type; + using _iterator = decltype(std::begin(std::declval<_container_t>())); + + template + void serialize(std::ostream& os, const Db& db) const + { + bool first = true; + for (const auto& entry: _container) + { + if (first) + first = false; + else + os << ','; + + value(entry).serialize(os, db); + } + } + + _container_t _container; + }; + + template + auto value_list(Container&& c) -> value_list_t::type> + { + static_assert(not is_value_t::type::value_type>::value, "value_list() is to be called with a container of non-sqlpp-type like std::vector, or std::list(string)"); + return { std::forward(c) }; + } + + template + constexpr const char* get_sql_name(const T&) + { + return std::decay::type::_name_t::_get_name(); + } + + +} + +#endif diff --git a/group_by.h b/group_by.h new file mode 100644 index 00000000..ec705ba7 --- /dev/null +++ b/group_by.h @@ -0,0 +1,68 @@ +/* + * 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_GROUP_BY_H +#define SQLPP_GROUP_BY_H + +#include +#include +#include + +#include +#include +#include + +namespace sqlpp +{ + template + struct group_by_t + { + // ensure one argument at least + static_assert(sizeof...(Expr), "at least one expression (e.g. a column) required in group_by()"); + + // check for duplicate expressions + static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in group_by()"); + + // check for invalid expressions + using _valid_expressions = typename detail::make_set_if::type; + static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in group_by()"); + + using _is_group_by = tag_yes; + + template + void serialize(std::ostream& os, Db& db) const + { + os << " GROUP BY "; + detail::serialize_tuple(os, db, _expressions, ','); + } + + std::tuple _expressions; + + }; + +} + +#endif diff --git a/having.h b/having.h new file mode 100644 index 00000000..2dc55268 --- /dev/null +++ b/having.h @@ -0,0 +1,54 @@ +/* + * 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_HAVING_H +#define SQLPP_HAVING_H + +#include +#include +#include + +namespace sqlpp +{ + template + struct having_t + { + static_assert(is_expression_t::value, "invalid expression argument in having()"); + + using _is_having = tag_yes; + + template + void serialize(std::ostream& os, Db& db) const + { + os << " HAVING "; + _expr.serialize(os, db); + } + + Expr _expr; + }; +} + +#endif diff --git a/insert.h b/insert.h new file mode 100644 index 00000000..70f2fd71 --- /dev/null +++ b/insert.h @@ -0,0 +1,114 @@ +/* + * 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_INSERT_H +#define SQLPP_INSERT_H + +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + // Hint: Columns/Values could be supported by .columns().values().values()... + // values could take values or assignments. The latter would be stripped + // The insert would store a vector of tuples of values. + // Hint: Select could be supported by perfect forwarding to the methods of _select member (always changing the whole type of the + // insert. + template< + typename Table = noop, + typename Assignments = noop + > + struct insert_t; + + template< + typename Table, + typename Assignments + > + struct insert_t + { + static_assert(is_noop::value or is_table_t
::value, "invalid 'Table' argument"); + static_assert(is_noop::value or is_assignment_list_t::value, "invalid 'Assignments' arguments"); + + template + using add_assignments_t = insert_t::type...>>; + + template + add_assignments_t set(Assignment&&... assignment) + { + static_assert(std::is_same::value, "cannot call set() twice"); + return { + _table, + {std::forward(assignment)...}, + }; + } + + template + const insert_t& serialize(std::ostream& os, Db& db) const + { + os << "INSERT INTO "; + _table.serialize(os, db); + if (is_noop::value) + os << "() VALUES()"; + else + _assignments.serialize(os, db); + return *this; + } + + template + insert_t& serialize(std::ostream& os, Db& db) + { + static_cast(this)->serialize(os, db); + return *this; + } + + template + std::size_t run(Db& db) const + { + constexpr bool calledSet = not is_noop::value; + constexpr bool requireSet = Table::_required_insert_columns::size::value > 0; + static_assert(calledSet or not requireSet, "calling set() required for given table"); + std::ostringstream oss; + serialize(oss, db); + return db.insert(oss.str()); + } + + Table _table; + Assignments _assignments; + }; + + template + constexpr insert_t::type> insert_into(Table&& table) + { + return {std::forward
(table)}; + } + +} + +#endif diff --git a/join.h b/join.h new file mode 100644 index 00000000..67be7b32 --- /dev/null +++ b/join.h @@ -0,0 +1,100 @@ +/* + * 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_JOIN_H +#define SQLPP_JOIN_H + +#include + +namespace sqlpp +{ + struct inner_join_t + { + static constexpr const char* _name = "INNER"; + }; + struct outer_join_t + { + static constexpr const char* _name = "OUTER"; + }; + struct left_join_t + { + static constexpr const char* _name = "LEFT OUTER"; + }; + struct right_join_t + { + static constexpr const char* _name = "RIGHT OUTER"; + }; + + template + struct join_t + { + static_assert(is_table_t::value, "invalid lhs argument for join()"); + static_assert(is_table_t::value, "invalid rhs argument for join()"); + static_assert(is_noop::value or is_expression_t::value, "invalid on expression in join().on()"); + + static_assert(Lhs::_table_set::template is_disjunct_from::value, "joined tables must not be identical"); + + using _is_table = typename std::conditional::value, + tag_no, + tag_yes>::type; + using _table_set = typename std::conditional::value, + void, + typename Lhs::_table_set::template join::type>::type; + + template + using add_on_t = join_t::type>; + + template + add_on_t on(Expr&& expr) + { + return { _lhs, _rhs, std::forward(expr) }; + } + + template + join_t::type> join(T&& t) + { + return { *this, std::forward(t) }; + } + + template + void serialize(std::ostream& os, Db& db) const + { + os << " ("; + _lhs.serialize(os, db); + os << ") " << JoinType::_name << " JOIN ("; + _rhs.serialize(os, db); + os << ") ON ("; + _on.serialize(os, db); + os << ")"; + } + + Lhs _lhs; + Rhs _rhs; + On _on; + }; +} + +#endif diff --git a/limit.h b/limit.h new file mode 100644 index 00000000..c6d7f366 --- /dev/null +++ b/limit.h @@ -0,0 +1,64 @@ +/* + * 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_LIMIT_H +#define SQLPP_LIMIT_H + +#include +#include +#include + +namespace sqlpp +{ + struct limit_t + { + using _is_limit = tag_yes; + + template + void serialize(std::ostream& os, Db& db) const + { + os << " LIMIT " << _limit; + } + + std::size_t _limit; + }; + + struct offset_t + { + using _is_offset = tag_yes; + + template + void serialize(std::ostream& os, Db& db) const + { + os << " OFFSET " << _offset; + } + + const std::size_t _offset; + }; + +} + +#endif diff --git a/multi_column.h b/multi_column.h new file mode 100644 index 00000000..a33cf69c --- /dev/null +++ b/multi_column.h @@ -0,0 +1,81 @@ +/* + * 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_MULTI_COLUMN_H +#define SQLPP_MULTI_COLUMN_H + +#include +#include + +namespace sqlpp +{ + template + struct multi_column_t + { + static_assert(detail::wrong::value, "invalid argument for multicolumn_t"); + }; + + template + struct multi_column_t> + { + using _named_expr_set = typename detail::make_set_if::type; + static_assert(_named_expr_set::size::value == sizeof...(NamedExpr), "multi_column parameters need to be named expressions"); + + using _name_t = typename AliasProvider::_name_t; + template + using _member_t = typename AliasProvider::template _member_t; + + struct _value_type: public no_value_t + { + using _is_named_expression = tag_yes; + }; + using _is_multi_column = tag_yes; + + template + void serialize(std::ostream& os, Db& db) const + { + detail::serialize_tuple(os, db, _columns, ','); + } + + std::tuple _columns; + }; + + namespace detail + { + template + using make_multi_column_t = + multi_column_t::type, decltype(make_expression_tuple(std::declval()...))>; + } + + template + detail::make_multi_column_t multi_column(AliasProvider&& aliasProvider, NamedExpr&&... namedExpr) + { + return { {std::forward(namedExpr)...}}; + } + +} + +#endif diff --git a/no_value.h b/no_value.h new file mode 100644 index 00000000..aac10366 --- /dev/null +++ b/no_value.h @@ -0,0 +1,47 @@ +/* + * 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_NO_VALUE_H +#define SQLPP_NO_VALUE_H + +#include + +namespace sqlpp +{ + // boolean value type + struct no_value_t + { + template + using _constraint = std::false_type; + + template + struct operators + { + }; + }; + +} +#endif diff --git a/noop.h b/noop.h new file mode 100644 index 00000000..d63bb31a --- /dev/null +++ b/noop.h @@ -0,0 +1,45 @@ +/* + * 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_NOOP_H +#define SQLPP_NOOP_H + +#include + +namespace sqlpp +{ + struct noop + { + template + void serialize(std::ostream& os, Db& db) const + {} + }; + + template + struct is_noop: std::is_same {}; + +} +#endif diff --git a/noop_fwd.h b/noop_fwd.h new file mode 100644 index 00000000..dccb845b --- /dev/null +++ b/noop_fwd.h @@ -0,0 +1,37 @@ +/* + * 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_NOOP_FWD_H +#define SQLPP_NOOP_FWD_H + +namespace sqlpp +{ + struct noop; + + template + struct is_noop; +} +#endif diff --git a/numeric.h b/numeric.h new file mode 100644 index 00000000..cfbed5d3 --- /dev/null +++ b/numeric.h @@ -0,0 +1,185 @@ +/* + * 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_NUMERIC_H +#define SQLPP_NUMERIC_H + +#include +#include +#include +#include +#include + +namespace sqlpp +{ + namespace detail + { + + // numeric value type + struct numeric + { + using _base_value_type = numeric; + using _is_numeric = tag_yes; + using _is_value = tag_yes; + using _is_expression = tag_yes; + + template + struct _result_entry_t + { + using _value_type = numeric; + _result_entry_t(const raw_result_row_t& row): + _is_valid(row.data != nullptr), + _is_null(row.data == nullptr or row.data[index] == nullptr), + _value(_is_null ? 0 : std::strtoll(row.data[index], nullptr, 10)) + {} + + _result_entry_t& operator=(const raw_result_row_t& row) + { + _is_valid = (row.data != nullptr); + _is_null = row.data == nullptr or row.data[index] == nullptr; + _value = _is_null ? 0 : std::strtoll(row.data[index], nullptr, 10); + return *this; + } + + template + void serialize(std::ostream& os, Db& db) const + { + os << value(); + } + + bool _is_trivial() const { return value() == 0; } + + bool is_null() const { return _is_null; } + int64_t value() const + { + if (not _is_valid) + throw exception("accessing value in non-existing row"); + return _value; + } + operator int64_t() const { return value(); } + + private: + bool _is_valid; + bool _is_null; + int64_t _value; + }; + + struct plus_ + { + using _value_type = numeric; + static constexpr const char* _name = "+"; + }; + + struct minus_ + { + using _value_type = numeric; + static constexpr const char* _name = "-"; + }; + + struct multiplies_ + { + using _value_type = numeric; + static constexpr const char* _name = "*"; + }; + + struct divides_ + { + using _value_type = numeric; + static constexpr const char* _name = "/"; + }; + + template + using _constraint = operand_t; + + template + struct operators: public basic_operators + { + template + nary_expression_t::type> operator +(T&& t) const + { + return { *static_cast(this), std::forward(t) }; + } + + template + nary_expression_t::type> operator -(T&& t) const + { + return { *static_cast(this), std::forward(t) }; + } + + template + nary_expression_t::type> operator *(T&& t) const + { + return { *static_cast(this), std::forward(t) }; + } + + template + nary_expression_t::type> operator /(T&& t) const + { + return { *static_cast(this), std::forward(t) }; + } + + template + auto operator +=(T&& t) const -> decltype(std::declval() = operator +(std::forward(t))) + { + return *static_cast(this) = operator +(std::forward(t)); + } + + template + auto operator -=(T&& t) const -> decltype(std::declval() = operator -(std::forward(t))) + { + return *static_cast(this) = operator -(std::forward(t)); + } + + template + auto operator /=(T&& t) const -> decltype(std::declval() = operator /(std::forward(t))) + { + return *static_cast(this) = operator /(std::forward(t)); + } + + template + auto operator *=(T&& t) const -> decltype(std::declval() = operator *(std::forward(t))) + { + return *static_cast(this) = operator *(std::forward(t)); + } + + + }; + }; + + template + std::ostream& operator<<(std::ostream& os, const numeric::_result_entry_t& e) + { + return os << e.value(); + } + } + + using tinyint = detail::numeric; + using smallint = detail::numeric; + using integer = detail::numeric; + using bigint = detail::numeric; + +} +#endif diff --git a/order_by.h b/order_by.h new file mode 100644 index 00000000..78710f5a --- /dev/null +++ b/order_by.h @@ -0,0 +1,64 @@ +/* + * 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_ORDER_BY_H +#define SQLPP_ORDER_BY_H + +#include +#include +#include +#include +#include + +namespace sqlpp +{ + template + struct order_by_t + { + // check for at least one order expression + static_assert(sizeof...(OrderExpr), "at least one select expression required in order_by()"); + + // check for duplicate order expressions + static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in order_by()"); + + // check for invalid order expressions + using _valid_expressions = typename detail::make_set_if::type; + static_assert(_valid_expressions::size::value == sizeof...(OrderExpr), "at least one argument is not a sort order expression in order_by()"); + + using _is_order_by = tag_yes; + + template + void serialize(std::ostream& os, Db& db) const + { + os << " ORDER BY "; + detail::serialize_tuple(os, db, _orderExpressions, ','); + } + + std::tuple _orderExpressions; + }; +} + +#endif diff --git a/raw_result_row.h b/raw_result_row.h new file mode 100644 index 00000000..0baaf9ff --- /dev/null +++ b/raw_result_row.h @@ -0,0 +1,44 @@ +/* + * 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_RAW_RESULT_ROW_H +#define SQLPP_RAW_RESULT_ROW_H + +namespace sqlpp +{ + struct raw_result_row_t + { + const char** data; + const size_t* len; + + bool operator==(const raw_result_row_t& rhs) const + { + return data == rhs.data and len == rhs.len; + } + }; +} + +#endif diff --git a/remove.h b/remove.h new file mode 100644 index 00000000..d4915cd7 --- /dev/null +++ b/remove.h @@ -0,0 +1,122 @@ +/* + * 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_REMOVE_H +#define SQLPP_REMOVE_H + +#include +#include +#include +#include +#include + +namespace sqlpp +{ + template< + typename Table, + typename Using = noop, + typename Where = noop + > + struct remove_t; + + template< + typename Table, + typename Using, + typename Where + > + struct remove_t + { + static_assert(is_noop
::value or is_table_t
::value, "invalid 'Table' argument"); + static_assert(is_noop::value or is_using_t::value, "invalid 'Using' argument"); + static_assert(is_noop::value or is_where_t::value, "invalid 'Where' argument"); + + template + using add_using_t = remove_t::type...>, Where>; + template + using add_where_t = remove_t::type>>; + + template + add_using_t using_(Tab&&... tab) + { + static_assert(std::is_same::value, "cannot call using() twice"); + static_assert(std::is_same::value, "cannot call using() after where()"); + return { + _table, + {{std::forward(tab)...}}, + _where + }; + } + + template + add_where_t where(Expr&& where) + { + static_assert(std::is_same::value, "cannot call where() twice"); + return { + _table, + _using, + {std::forward(where)}, + }; + } + + template + const remove_t& serialize(std::ostream& os, Db& db) const + { + os << "DELETE FROM "; + _table.serialize(os, db); + _using.serialize(os, db); + _where.serialize(os, db); + return *this; + } + + template + remove_t& serialize(std::ostream& os, Db& db) + { + static_cast(this)->serialize(os, db); + return *this; + } + + template + std::size_t run(Db& db) const + { + std::ostringstream oss; + serialize(oss, db); + return db.remove(oss.str()); + } + + Table _table; + Using _using; + Where _where; + }; + + template + constexpr remove_t::type> remove_from(Table&& table) + { + return {std::forward
(table)}; + } + +} + +#endif diff --git a/result.h b/result.h new file mode 100644 index 00000000..81e09c1c --- /dev/null +++ b/result.h @@ -0,0 +1,116 @@ +/* + * 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_RESULT_H +#define SQLPP_RESULT_H + +#include + +#include + +namespace sqlpp +{ + template + struct result_t + { + using db_result_t = typename Db::result; + + // Iterator + class iterator + { + public: + iterator(db_result_t& result): + _result(result), + _raw_result_row({}), + _result_row(_raw_result_row) + { + std::cerr << "result::iterator::end-constructor" << std::endl; + } + + iterator(db_result_t& result, const raw_result_row_t& raw_result_row): + _result(result), + _raw_result_row(raw_result_row), + _result_row(_raw_result_row) + { + std::cerr << "result::iterator::begin-constructor" << std::endl; + } + + const ResultRow& operator*() const + { + return _result_row; + } + + const ResultRow* operator->() const + { + return &_result_row; + } + + bool operator==(const iterator& rhs) const + { + return _result == rhs._result and _raw_result_row == rhs._raw_result_row; + } + + bool operator!=(const iterator& rhs) const + { + return not (operator==(rhs)); + } + + void operator++() + { + _raw_result_row = _result.next(); + _result_row = _raw_result_row; + } + + db_result_t& _result; + raw_result_row_t _raw_result_row; + ResultRow _result_row; + }; + + iterator begin() + { + return iterator(_result, _result.next()); + } + + iterator end() + { + return _result; + } + + const ResultRow operator*() + { + return {_result.next()}; + } + + iterator operator->() + { + return begin(); + } + + db_result_t _result; + }; +} + +#endif diff --git a/result_row.h b/result_row.h new file mode 100644 index 00000000..509a9acd --- /dev/null +++ b/result_row.h @@ -0,0 +1,119 @@ +/* + * 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_RESULT_ROW_H +#define SQLPP_RESULT_ROW_H + +#include +#include +#include +namespace sqlpp +{ + namespace detail + { + template + struct result_row_impl; + + template + struct result_row_impl: + public NamedExpr::template _member_t>, + public result_row_impl + { + using _field = typename NamedExpr::template _member_t>; + using _rest = result_row_impl; + + result_row_impl(const raw_result_row_t& raw_result_row): + _field({raw_result_row}), + _rest(raw_result_row) + {} + + result_row_impl& operator=(const raw_result_row_t& raw_result_row) + { + _field::operator=({raw_result_row}); + _rest::operator=(raw_result_row); + return *this; + } + }; + + template + struct result_row_impl>, Rest...>: + public AliasProvider::template _member_t>, // level prevents identical closures to be present twice in the inheritance tree + public result_row_impl + { + using _multi_field = typename AliasProvider::template _member_t>; + using _rest = result_row_impl; + + result_row_impl(const raw_result_row_t& raw_result_row): + _multi_field({raw_result_row}), + _rest(raw_result_row) + {} + + result_row_impl& operator=(const raw_result_row_t& raw_result_row) + { + _multi_field::operator=({raw_result_row}); + _rest::operator=(raw_result_row); + return *this; + } + }; + + template + struct result_row_impl + { + result_row_impl(const raw_result_row_t& raw_result_row) + {} + + result_row_impl& operator=(const raw_result_row_t& raw_result_row) + { + return *this; + } + }; + } + + template + struct result_row_t: public detail::result_row_impl<0, 0, NamedExpr...> + { + bool _is_row; + + result_row_t(const raw_result_row_t& raw_result_row): + detail::result_row_impl<0, 0, NamedExpr...>(raw_result_row), + _is_row(raw_result_row.data != nullptr) + {} + + result_row_t& operator=(const raw_result_row_t& raw_result_row) + { + detail::result_row_impl<0, 0, NamedExpr...>::operator=(raw_result_row); + _is_row = raw_result_row.data != nullptr; + return *this; + } + + explicit operator bool() const + { + return _is_row; + } + }; +} + +#endif diff --git a/select.h b/select.h new file mode 100644 index 00000000..8342d7f9 --- /dev/null +++ b/select.h @@ -0,0 +1,437 @@ +/* + * 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_SELECT_H +#define SQLPP_SELECT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace sqlpp +{ + // select template, to be used as an r_value + template< + typename Flags, + typename... NamedExpr, + typename From, + typename Where, + typename GroupBy, + typename Having, + typename OrderBy, + typename Limit, + typename Offset + > + struct select_t>, From, Where, GroupBy, Having, OrderBy, Limit, Offset> + : public select_expression_list_t>::_value_type::template operators>, + From, + Where, + GroupBy, + Having, + OrderBy, + Limit, + Offset>> + { + using ExpressionList = select_expression_list_t>; + + static_assert(is_noop::value or is_select_flag_list_t::value, "invalid list of select flags"); + static_assert(is_select_expression_list_t::value, "invalid list of select expressions"); + static_assert(is_noop::value or is_from_t::value, "invalid 'from' argument"); + static_assert(is_noop::value or is_where_t::value, "invalid 'where' argument"); + static_assert(is_noop::value or is_group_by_t::value, "invalid 'group by' arguments"); + static_assert(is_noop::value or is_having_t::value, "invalid 'having' arguments"); + static_assert(is_noop::value or is_order_by_t::value, "invalid 'order by' arguments"); + static_assert(is_noop::value or is_limit_t::value, "invalid 'limit' arguments"); + static_assert(is_noop::value or is_offset_t::value, "invalid 'offset' arguments"); + + using _is_select = tag_yes; + using _requires_braces = tag_yes; + + template + using add_from_t = select_t::type...>, Where, GroupBy, Having, OrderBy, Limit, Offset>; + template + using add_where_t = select_t::type>, GroupBy, Having, OrderBy, Limit, Offset>; + template + using add_group_by_t = select_t::type...>, Having, OrderBy, Limit, Offset>; + template + using add_having_t = select_t::type>, OrderBy, Limit, Offset>; + template + using add_order_by_t = select_t::type...>, Limit, Offset>; + using add_limit_t = select_t; + using add_offset_t = select_t; + + using result_row_t = result_row_t; + + // Indicators + using _value_type = typename std::conditional< + is_noop::value, + no_value_t, // If there is no from, the select is not complete (this logic is a bit simple, but better than nothing) + typename ExpressionList::_value_type>::type; + + using _name_t = typename ExpressionList::_name_t; + template + using _member_t = typename ExpressionList::template _member_t; + + // The standard constructors, assigment operators and destructor + select_t(Flags&& flags, ExpressionList&& expression_list): + _flags(std::move(flags)), + _expression_list(std::move(expression_list)) + { + static_assert(std::is_same>::value, + "basic constructor only available for select_t (default template parameters)"); + } + + constexpr select_t(const select_t& rhs): + _flags(rhs._flags), + _expression_list(rhs._expression_list), + _from(rhs._from), + _where(rhs._where), + _group_by(rhs._group_by), + _having(rhs._having), + _order_by(rhs._order_by), + _limit(rhs._limit), + _offset(rhs._offset) + { + } + + constexpr select_t(select_t&& rhs): + _flags(std::move(rhs._flags)), + _expression_list(std::move(rhs._expression_list)), + _from(std::move(rhs._from)), + _where(std::move(rhs._where)), + _group_by(std::move(rhs._group_by)), + _having(std::move(rhs._having)), + _order_by(std::move(rhs._order_by)), + _limit(std::move(rhs._limit)), + _offset(std::move(rhs._offset)) + { + } + + select_t& operator=(const select_t& rhs) + { + _flags = rhs._flags; + _expression_list = rhs._expression_list; + _from = rhs._from; + _where = rhs._where; + _group_by = rhs._group_by; + _having = rhs._having; + _order_by = rhs._order_by; + _offset = rhs._offset; + _limit = rhs._limit; + } + + select_t& operator=(select_t&& rhs) + { + _flags = std::move(rhs._flags); + _expression_list = std::move(rhs._expression_list); + _from = std::move(rhs._from); + _where = std::move(rhs._where); + _group_by = std::move(rhs._group_by); + _having = std::move(rhs._having); + _order_by = std::move(rhs._order_by); + _limit = std::move(rhs._limit); + _offset = std::move(rhs._offset); + } + + ~select_t() = default; + + // Other constructors + + constexpr select_t(Flags&& flags, ExpressionList&& expression_list, From&& from, + Where&& where, GroupBy&& group_by, Having&& having, + OrderBy&& order_by, Limit&& limit, Offset&& offset): + _flags(std::move(flags)), + _expression_list(std::move(expression_list)), + _from(std::move(from)), + _where(std::move(where)), + _group_by(std::move(group_by)), + _having(std::move(having)), + _order_by(std::move(order_by)), + _limit(std::move(limit)), + _offset(std::move(offset)) + { + } + + constexpr select_t(const Flags& flags, const ExpressionList& expression_list, const From& from, + const Where& where, const GroupBy& group_by, const Having& having, + const OrderBy& order_by, const Limit& limit, const Offset& offset): + _flags(flags), + _expression_list(expression_list), + _from(from), + _where(where), + _group_by(group_by), + _having(having), + _order_by(order_by), + _limit(limit), + _offset(offset) + { + } + + // sqlpp functions + template + add_from_t from(Table&&... table) + { + static_assert(not is_noop::value, "cannot call from() without having selected anything"); + static_assert(is_noop::value, "cannot call from() twice for a single select"); + return { + _flags, + _expression_list, + {{std::forward
(table)...}}, + _where, + _group_by, + _having, + _order_by, + _limit, + _offset + }; + } + + template + add_where_t where(Expr&& expr) + { + static_assert(not is_noop::value, "cannot call where() without a from()"); + static_assert(is_noop::value, "cannot call where() twice for a single select"); + return { + _flags, + _expression_list, + _from, + {std::forward(expr)}, + _group_by, + _having, + _order_by, + _limit, + _offset + }; + } + + template + add_group_by_t group_by(Col&&... column) + { + static_assert(not is_noop::value, "cannot call group_by() without a from()"); + static_assert(is_noop::value, "cannot call group_by() twice for a single select"); + return { + _flags, + _expression_list, + _from, + _where, + {{std::forward(column)...}}, + _having, + _order_by, + _limit, + _offset + }; + } + + template + add_having_t having(Expr&& expr) + { + static_assert(not is_noop::value, "cannot call having() without a group_by"); + static_assert(is_noop::value, "cannot call having() twice for a single select"); + return { + _flags, + _expression_list, + _from, + _where, + _group_by, + {std::forward(expr)}, + _order_by, + _limit, + _offset + }; + } + + template + add_order_by_t order_by(OrderExpr&&... expr) + { + static_assert(not is_noop::value, "cannot call order_by() without a from()"); + static_assert(is_noop::value, "cannot call order_by() twice for a single select"); + return { + _flags, + _expression_list, + _from, + _where, + _group_by, + _having, + {{std::forward(expr)...}}, + _limit, + _offset + }; + } + + add_limit_t limit(std::size_t limit) + { + static_assert(not is_noop::value, "cannot call limit() without a from()"); + static_assert(is_noop::value, "cannot call limit() twice for a single select"); + return { + _flags, + _expression_list, + _from, + _where, + _group_by, + _having, + _order_by, + {limit}, + _offset + }; + } + + add_offset_t offset(std::size_t offset) + { + static_assert(not is_noop::value, "cannot call offset() without a limit"); + static_assert(is_noop::value, "cannot call offset() twice for a single select"); + return { + _flags, + _expression_list, + _from, + _where, + _group_by, + _having, + _order_by, + _limit, + {offset} + }; + } + + // Turn into pseudo table or named expression + using pseudo_table_t = select_pseudo_table_t< + Flags, + ExpressionList, + From, + Where, + GroupBy, + Having, + OrderBy, + Limit, + Offset, + NamedExpr...>; + + template + using alias_t = typename pseudo_table_t::template alias_t; + + template + typename std::enable_if::value, alias_t>::type as(const AliasProvider& aliasProvider) const + { + return pseudo_table_t( + _flags, + _expression_list, + _from, + _where, + _group_by, + _having, + _order_by, + _limit, + _offset).as(aliasProvider); + } + + // Serialize + template + select_t& serialize(std::ostream& os, Db& db) + { + detail::serialize_select(os, db, *this); + return *this; + } + + template + const select_t& serialize(std::ostream& os, Db& db) const + { + detail::serialize_select(os, db, *this); + return *this; + } + + + // Execute + template + result_t run(Db& db) const + { + static_assert(not is_noop::value, "cannot run select without having selected anything"); + static_assert(is_from_t::value, "cannot run select without a from()"); + // FIXME: Check for missing aliases (if references are used) + // FIXME: Check for missing tables + + std::ostringstream oss; + serialize(oss, db); + return {db.select(oss.str())}; + + //serialize using db + //run using db and return result_set + } + + Flags _flags; + ExpressionList _expression_list; + From _from; + Where _where; + GroupBy _group_by; + Having _having; + OrderBy _order_by; + Limit _limit; + Offset _offset; + }; + + // construct select flag list + namespace detail + { + template + using make_select_flag_list_t = + select_flag_list_t()...))>; + } + + // construct select expression list + namespace detail + { + template + using make_select_expression_list_t = + select_expression_list_t()...))>; + } + + template + select_t, detail::make_select_expression_list_t> select(NamedExpr&&... namedExpr) + { + return { + { detail::make_flag_tuple(std::forward(namedExpr)...) }, + { detail::make_expression_tuple(std::forward(namedExpr)...) } + }; + } +} +#endif diff --git a/select_expression_list.h b/select_expression_list.h new file mode 100644 index 00000000..1a7949a0 --- /dev/null +++ b/select_expression_list.h @@ -0,0 +1,113 @@ +/* + * 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_SELECT_EXPRESSION_LIST_H +#define SQLPP_SELECT_EXPRESSION_LIST_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + namespace detail + { + template + void serialize_select(std::ostream& os, Db& db, const Select& select) + { + os << "SELECT "; + + select._flags.serialize(os, db); + select._expression_list.serialize(os, db); + select._from.serialize(os, db); + select._where.serialize(os, db); + select._group_by.serialize(os, db); + select._having.serialize(os, db); + select._order_by.serialize(os, db); + select._limit.serialize(os, db); + select._offset.serialize(os, db); + }; + + template + struct get_first_argument + { + using type = T; + }; + } + template + struct select_expression_list_t> + { + // check for at least one select expression + static_assert(sizeof...(NamedExpr), "at least one select expression required"); + + // check for duplicate select expressions + static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected"); + + // check for invalid select expressions + template + struct is_valid_expression_t: public std::integral_constant::value or is_multi_column_t::value> {}; + using _valid_expressions = typename detail::make_set_if::type; + static_assert(_valid_expressions::size::value == sizeof...(NamedExpr), "at least one argument is not a named expression"); + + // check for duplicate select expression names + static_assert(not detail::has_duplicates...>::value, "at least one duplicate name detected"); + + // declare this to be a select expression + using _is_select_expression_list = tag_yes; + + // provide type information for sub-selects that are used as expressions + struct _column_type {}; + struct _value_type: std::conditional::type::_value_type, no_value_t>::type + { + using _is_expression = typename std::conditional::type; + using _is_named_expression = typename std::conditional::type; + using _is_alias = tag_no; + }; + struct _no_name_t {}; + using _name_t = typename std::conditional::type::_name_t, _no_name_t>::type; + + template + struct _no_member_t {}; + template + using _member_t = typename std::conditional::type::template _member_t, _no_member_t>::type; + + template + void serialize(std::ostream& os, Db& db) const + { + detail::serialize_tuple(os, db, _expressions, ','); + } + + std::tuple _expressions; + }; + +} + +#endif diff --git a/select_flag_list.h b/select_flag_list.h new file mode 100644 index 00000000..d3d581d6 --- /dev/null +++ b/select_flag_list.h @@ -0,0 +1,110 @@ +/* + * 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_SELECT_FLAGS_H +#define SQLPP_SELECT_FLAGS_H + +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + // standard select flags + struct all_t + { + struct _value_type + { + using _is_select_flag = tag_yes; + }; + + template + void serialize(std::ostream& os, const Db&) const + { + os << "ALL"; + } + }; + static constexpr all_t all = {}; + + struct distinct_t + { + struct _value_type + { + using _is_select_flag = tag_yes; + }; + + template + void serialize(std::ostream& os, const Db&) const + { + os << "DISTINCT"; + } + }; + static constexpr distinct_t distinct = {}; + + struct straight_join_t + { + struct _value_type + { + using _is_select_flag = tag_yes; + }; + + template + void serialize(std::ostream& os, const Db&) const + { + os << "STRAIGHT_JOIN"; + } + }; + static constexpr straight_join_t straight_join = {}; + + // select_flag_list_t + template + struct select_flag_list_t> + { + // check for duplicate order expressions + static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in select flag list"); + + // check for invalid order expressions + using _valid_flags = typename detail::make_set_if::type; + static_assert(_valid_flags::size::value == sizeof...(Flag), "at least one argument is not a select flag in select flag list"); + + using _is_select_flag_list = tag_yes; + + template + void serialize(std::ostream& os, Db& db) const + { + detail::serialize_tuple(os, db, _flags, ' '); + os << ' '; + } + + std::tuple _flags; + }; + +} + +#endif diff --git a/select_fwd.h b/select_fwd.h new file mode 100644 index 00000000..d7d21eba --- /dev/null +++ b/select_fwd.h @@ -0,0 +1,70 @@ +/* + * 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_SELECT_FWD_H +#define SQLPP_SELECT_FWD_H + +#include +#include + +namespace sqlpp +{ + // select flags + struct all_t; + struct distinct_t; + struct straight_join_t; + + template struct select_flag_list_t; + template struct select_expression_list_t; + + template struct from_t; + + template struct where_t; + + template struct group_by_t; + + template struct having_t; + + template struct order_by_t; + + struct limit_t; + + struct offset_t; + + template< + typename Flags = noop, + typename ExpressionList = noop, + typename From = noop, + typename Where = noop, + typename GroupBy = noop, + typename Having = noop, + typename OrderBy = noop, + typename Limit = noop, + typename Offset = noop + > + struct select_t; +} +#endif diff --git a/select_pseudo_table.h b/select_pseudo_table.h new file mode 100644 index 00000000..3c9a026d --- /dev/null +++ b/select_pseudo_table.h @@ -0,0 +1,123 @@ +/* + * 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_SELECT_PSEUDO_TABLE_H +#define SQLPP_SELECT_PSEUDO_TABLE_H + +#include + +namespace sqlpp +{ + // provide type information for sub-selects that are used as named expressions or tables + template + struct select_column_spec_t + { + using _name_t = typename Expr::_name_t; + template + using _member_t = typename Expr::template _member_t; + using _value_type = typename Expr::_value_type; + struct _column_type {}; + }; + + template< + typename Flags, + typename ExpressionList, + typename From, + typename Where, + typename GroupBy, + typename Having, + typename OrderBy, + typename Limit, + typename Offset, + typename... NamedExpr + > + struct select_pseudo_table_t: public sqlpp::table_base_t, select_column_spec_t...> + { + using _value_type = no_value_t; + + select_pseudo_table_t(const Flags& flags, const ExpressionList& expression_list, const From& from, + const Where& where, const GroupBy& group_by, const Having& having, + const OrderBy& order_by, const Limit& limit, const Offset& offset): + _flags(flags), + _expression_list(expression_list), + _from(from), + _where(where), + _group_by(group_by), + _having(having), + _order_by(order_by), + _limit(limit), + _offset(offset) + { + std::cerr << "Copying arguments into pseudo_table" << std::endl; + //std::cerr << _limit._limit << std::endl; + } + + select_pseudo_table_t(const select_pseudo_table_t& rhs): + _flags(rhs._flags), + _expression_list(rhs._expression_list), + _from(rhs._from), + _where(rhs._where), + _group_by(rhs._group_by), + _having(rhs._having), + _order_by(rhs._order_by), + _limit(rhs._limit), + _offset(rhs._offset) + { + std::cerr << "Copying pseudo_table" << std::endl; + //std::cerr << _limit._limit << std::endl; + } + + template + void serialize(std::ostream& os, Db& db) const + { + //std::cerr << "pseudo_table::serialize: " << _limit._limit << std::endl; + detail::serialize_select(os, db, *this); + } + + Flags _flags; + ExpressionList _expression_list; + From _from; + Where _where; + GroupBy _group_by; + Having _having; + OrderBy _order_by; + Limit _limit; + Offset _offset; + }; + +} + +#endif diff --git a/sort_order.h b/sort_order.h new file mode 100644 index 00000000..b4008f63 --- /dev/null +++ b/sort_order.h @@ -0,0 +1,62 @@ +/* + * 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_SORT_ORDER_H +#define SQLPP_SORT_ORDER_H + +namespace sqlpp +{ + enum class sort_type + { + asc, + desc + }; + + template + struct sort_order_t + { + using _is_sort_order = tag_yes; + + template + void serialize(std::ostream& os, Db& db) const + { + _expression.serialize(os, db); + switch(SortType) + { + case sort_type::asc: + os << " ASC"; + break; + default: + os << " DESC"; + break; + } + } + + Expression _expression; + }; +} + +#endif diff --git a/table_base.h b/table_base.h new file mode 100644 index 00000000..1c54b36f --- /dev/null +++ b/table_base.h @@ -0,0 +1,113 @@ +/* + * 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_TABLE_BASE_H +#define SQLPP_TABLE_BASE_H + +#include +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + template + struct table_base_t: public ColumnSpec::template _member_t>... + { + using _table_set = detail::set
; // Hint need a set here to be similar to a join (which always represents more than one table) + using _all_columns = typename detail::make_set...>::type; + 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...>; + + using _is_table = tag_yes; + + template + join_t::type> join(T&& t) + { + return { *static_cast(this), std::forward(t) }; + } + + template + struct alias_t: public ColumnSpec::template _member_t>... + { + using _is_table = tag_yes; + using _table_set = detail::set; + + struct _value_type: Table::_value_type + { + using _is_expression = tag_no; + using _is_named_expression = copy_type_trait; + using _is_alias = tag_yes; + }; + + using _name_t = typename AliasProvider::_name_t; + using _all_of_t = std::tuple...>; + + alias_t(const Table& table): + _table(table) + {} + + alias_t(Table&& table): + _table(std::move(table)) + {} + + template + void serialize(std::ostream& os, Db& db) const + { + os << "("; _table.serialize(os, db); os << ") AS " << _name_t::_get_name(); + } + + Table _table; + }; + + template + alias_t as(const AliasProvider&) const + { + return {*static_cast(this)}; + } + + template + void serialize(std::ostream& os, Db& db) const + { + static_cast(this)->serialize(os, db); + } + + }; + + template + auto all_of(Table&& t) -> typename std::decay
::type::_all_of_t + { + return {}; + } + +} + +#endif + diff --git a/text.h b/text.h new file mode 100644 index 00000000..6eeb64ab --- /dev/null +++ b/text.h @@ -0,0 +1,138 @@ +/* + * 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_TEXT_H +#define SQLPP_TEXT_H + +#include +#include +#include +#include +#include + +namespace sqlpp +{ + namespace detail + { + struct text; + struct concat_ + { + using _value_type = detail::text; + static constexpr const char* _name = "CONCAT"; + }; + + struct like_ + { + using _value_type = boolean; + static constexpr const char* _name = "LIKE"; + }; + + // text value type + struct text + { + using _base_value_type = text; + using _is_text = tag_yes; + using _is_value = tag_yes; + using _is_expression = tag_yes; + + template + struct _result_entry_t + { + _result_entry_t(const raw_result_row_t& row): + _is_valid(row.data != nullptr), + _is_null(row.data == nullptr or row.data[index] == nullptr), + _value(_is_null ? "" : std::string(row.data[index], row.data[index] + row.len[index])) + {} + + _result_entry_t& operator=(const raw_result_row_t& row) + { + _is_valid = (row.data != nullptr); + _is_null = row.data == nullptr or row.data[index] == nullptr; + _value = _is_null ? "" : std::string(row.data[index], row.data[index] + row.len[index]); + return *this; + } + + template + void serialize(std::ostream& os, Db& db) const + { + os << value(); + } + + bool _is_trivial() const { return value().empty(); } + + bool operator==(const std::string& rhs) const { return value() == rhs; } + bool operator!=(const std::string& rhs) const { return not operator==(rhs); } + + bool is_null() const { return _is_null; } + std::string value() const + { + if (not _is_valid) + throw exception("accessing value in non-existing row"); + return _value; + } + operator std::string() const { return value(); } + + private: + bool _is_valid; + bool _is_null; + std::string _value; + }; + + template + using _constraint = operand_t; + + struct plus_ + { + using _value_type = boolean; + static constexpr const char* _name = "+"; + }; + + template + struct operators: public basic_operators + { + + template + nary_function_t::type> operator+(T&& t) const + { + return { *static_cast(this), std::forward(t) }; + } + + }; + }; + + template + std::ostream& operator<<(std::ostream& os, const text::_result_entry_t& e) + { + return os << e.value(); + } + } + + using text = detail::text; + using varchar = detail::text; + using char_ = detail::text; + +} +#endif diff --git a/transaction.h b/transaction.h new file mode 100644 index 00000000..2e11223d --- /dev/null +++ b/transaction.h @@ -0,0 +1,96 @@ +/* + * 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_TRANSACTION_H +#define SQLPP_TRANSACTION_H + +#include + +namespace sqlpp +{ + static constexpr bool quiet_auto_rollback = false; + static constexpr bool report_auto_rollback = true; + + template + class transaction_t + { + Db& _db; + const bool _report_unfinished_transaction; + bool _finished = false; + + public: + transaction_t(Db& db, bool report_unfinished_transaction): + _db(db), + _report_unfinished_transaction(report_unfinished_transaction) + { + _db.start_transaction(); + } + + transaction_t(const transaction_t&) = delete; + transaction_t(transaction_t&&) = default; + transaction_t& operator=(const transaction_t&) = delete; + transaction_t& operator=(transaction_t&&) = delete; + + ~transaction_t() + { + if (not _finished) + { + try + { + _db.rollback_transaction(_report_unfinished_transaction); + } + catch(const std::exception& e) + { + _db.report_rollback_failure(std::string("auto rollback failed: ") + e.what()); + } + catch(...) + { + _db.report_rollback_failure("auto rollback failed with unknown exception"); + } + } + } + + void commit() + { + _finished = true; + _db.commit_transaction(); + } + + void rollback() + { + _finished = true; + _db.rollback_transaction(false); + } + }; + + template + transaction_t::type> start_transaction(Db& db, bool report_unfinished_transaction = report_auto_rollback) + { + return { db, report_unfinished_transaction }; + }; +} + +#endif diff --git a/type_traits.h b/type_traits.h new file mode 100644 index 00000000..b28172c0 --- /dev/null +++ b/type_traits.h @@ -0,0 +1,117 @@ +/* + * 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_TYPE_TRAITS_H +#define SQLPP_TYPE_TRAITS_H + +#include +#include +namespace sqlpp +{ +#define SQLPP_IS_VALUE_TRAIT_GENERATOR(name) \ + namespace detail\ + {\ + template\ + struct is_##name##_impl: std::false_type {};\ + template\ + struct is_##name##_impl::value>::type>: std::true_type {};\ + }\ + template\ + struct is_##name##_t: detail::is_##name##_impl {}; + +#define SQLPP_IS_COLUMN_TRAIT_GENERATOR(name) \ + namespace detail\ + {\ + template\ + struct name##_impl: std::false_type {};\ + template\ + struct name##_impl::value>::type>: std::true_type {};\ + }\ + template\ + struct name##_t: detail::name##_impl {}; + +#define SQLPP_TYPE_TRAIT_GENERATOR(name) \ + namespace detail\ + {\ + template\ + struct name##_impl: std::false_type {};\ + template\ + struct name##_impl::value>::type>: std::true_type {};\ + }\ + template\ + struct name##_t: detail::name##_impl {}; + + SQLPP_IS_VALUE_TRAIT_GENERATOR(boolean); + SQLPP_IS_VALUE_TRAIT_GENERATOR(numeric); + SQLPP_IS_VALUE_TRAIT_GENERATOR(text); + SQLPP_IS_VALUE_TRAIT_GENERATOR(value); + SQLPP_IS_VALUE_TRAIT_GENERATOR(expression); + SQLPP_IS_VALUE_TRAIT_GENERATOR(named_expression); + SQLPP_IS_VALUE_TRAIT_GENERATOR(alias); // FIXME: Is this really part of the value? + SQLPP_IS_VALUE_TRAIT_GENERATOR(select_flag); + + SQLPP_IS_COLUMN_TRAIT_GENERATOR(must_not_insert); + SQLPP_IS_COLUMN_TRAIT_GENERATOR(must_not_update); + SQLPP_IS_COLUMN_TRAIT_GENERATOR(require_insert); + SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null); + SQLPP_IS_COLUMN_TRAIT_GENERATOR(trivial_value_is_null); + + SQLPP_TYPE_TRAIT_GENERATOR(is_table); + SQLPP_TYPE_TRAIT_GENERATOR(is_select); + SQLPP_TYPE_TRAIT_GENERATOR(is_select_flag_list); + SQLPP_TYPE_TRAIT_GENERATOR(is_select_expression_list); + SQLPP_TYPE_TRAIT_GENERATOR(is_from); + SQLPP_TYPE_TRAIT_GENERATOR(is_where); + SQLPP_TYPE_TRAIT_GENERATOR(is_group_by); + SQLPP_TYPE_TRAIT_GENERATOR(is_having); + SQLPP_TYPE_TRAIT_GENERATOR(is_order_by); + SQLPP_TYPE_TRAIT_GENERATOR(is_limit); + SQLPP_TYPE_TRAIT_GENERATOR(is_offset); + SQLPP_TYPE_TRAIT_GENERATOR(is_using); + SQLPP_TYPE_TRAIT_GENERATOR(is_column_list); + SQLPP_TYPE_TRAIT_GENERATOR(is_multi_column); + SQLPP_TYPE_TRAIT_GENERATOR(is_value_list); + SQLPP_TYPE_TRAIT_GENERATOR(is_assignment); + SQLPP_TYPE_TRAIT_GENERATOR(is_assignment_list); + SQLPP_TYPE_TRAIT_GENERATOR(is_sort_order); + SQLPP_TYPE_TRAIT_GENERATOR(requires_braces); + + template class IsTag> + using copy_type_trait = typename std::conditional::value, detail::tag, void>::type; + + template class IsCorrectType> + struct operand_t + { + using type = typename detail::wrap_operand::type>::type; + static_assert(not is_alias_t::value, "expression operand must not be an alias"); + static_assert(is_expression_t::value, "expression required"); + static_assert(IsCorrectType::value, "invalid operand type"); + }; + + +} + +#endif diff --git a/update.h b/update.h new file mode 100644 index 00000000..e69ba0dc --- /dev/null +++ b/update.h @@ -0,0 +1,122 @@ +/* + * 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_UPDATE_H +#define SQLPP_UPDATE_H + +#include +#include +#include +#include +#include + +namespace sqlpp +{ + template< + typename Table = noop, + typename Assignments = noop, + typename Where = noop + > + struct update_t; + + template< + typename Table, + typename Assignments, + typename Where + > + struct update_t + { + static_assert(is_noop
::value or is_table_t
::value, "invalid 'Table' argument"); + static_assert(is_noop::value or is_assignment_list_t::value, "invalid 'Assignments' arguments"); + static_assert(is_noop::value or is_where_t::value, "invalid 'Where' argument"); + + template + using add_assignments_t = update_t::type...>, Where>; + template + using add_where_t = update_t::type>>; + + template + add_assignments_t set(Assignment&&... assignment) + { + static_assert(std::is_same::value, "cannot call set() twice"); + return { + _table, + {{std::forward(assignment)...}}, + _where, + }; + } + + template + add_where_t where(Expr&& where) + { + static_assert(not std::is_same::value, "cannot call where() if set() hasn't been called yet"); + static_assert(std::is_same::value, "cannot call where() twice"); + return { + _table, + _assignments, + {std::forward(where)}, + }; + } + + template + const update_t& serialize(std::ostream& os, Db& db) const + { + os << "UPDATE "; + _table.serialize(os, db); + _assignments.serialize(os, db); + _where.serialize(os, db); + return *this; + } + + template + update_t& serialize(std::ostream& os, Db& db) + { + static_cast(this)->serialize(os, db); + return *this; + } + + template + std::size_t run(Db& db) const + { + std::ostringstream oss; + serialize(oss, db); + return db.update(oss.str()); + } + + Table _table; + Assignments _assignments; + Where _where; + }; + + template + constexpr update_t::type> update(Table&& table) + { + return {std::forward
(table)}; + } + +} + +#endif diff --git a/using.h b/using.h new file mode 100644 index 00000000..b26024ef --- /dev/null +++ b/using.h @@ -0,0 +1,54 @@ +/* + * 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_USING_H +#define SQLPP_USING_H + +#include +#include +#include + +namespace sqlpp +{ + template + struct using_t + { + using _is_using = tag_yes; + + static_assert(sizeof...(Table), "at least one table argument required in using"); + + template + void serialize(std::ostream& os, Db& db) const + { + os << " USING "; + detail::serialize_tuple(os, db, _tables, ','); + } + + std::tuple _tables; + }; +} + +#endif diff --git a/where.h b/where.h new file mode 100644 index 00000000..2e0782e1 --- /dev/null +++ b/where.h @@ -0,0 +1,56 @@ +/* + * 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_WHERE_H +#define SQLPP_WHERE_H + +#include +#include +#include +#include + +namespace sqlpp +{ + template + struct where_t + { + static_assert(is_expression_t::value, "invalid expression argument in where()"); + + using _is_where = tag_yes; + + template + void serialize(std::ostream& os, Db& db) const + { + os << " WHERE "; + _expr.serialize(os, db); + } + + Expr _expr; + }; + +} + +#endif