mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Merge branch 'release/0.58'
This commit is contained in:
commit
e9f6f07677
@ -13,6 +13,7 @@ compiler:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
- CONFIG=Release
|
- CONFIG=Release
|
||||||
|
- CONFIG=Release TESTS_CXX_STD=17
|
||||||
#- CONFIG=Debug
|
#- CONFIG=Debug
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
@ -37,7 +38,8 @@ before_script:
|
|||||||
sudo apt-get install python-pyparsing;
|
sudo apt-get install python-pyparsing;
|
||||||
fi
|
fi
|
||||||
- if [[ "$CXX" = "g++" && "$CONFIG" = "Debug" && "$TRAVIS_OS_NAME" = "linux" ]]; then export CXXFLAGS="--coverage"; fi
|
- if [[ "$CXX" = "g++" && "$CONFIG" = "Debug" && "$TRAVIS_OS_NAME" = "linux" ]]; then export CXXFLAGS="--coverage"; fi
|
||||||
- cmake .. -DCMAKE_BUILD_TYPE=$CONFIG -DCMAKE_PREFIX_PATH=$PWD/../date
|
- if [[ -n "${TESTS_CXX_STD:-}" && "$TRAVIS_OS_NAME" = "osx" ]]; then ADD_OPTS="-DSQLPP11_TESTS_CXX_STD=$TESTS_CXX_STD"; fi
|
||||||
|
- cmake .. -DCMAKE_BUILD_TYPE=$CONFIG -DCMAKE_PREFIX_PATH=$PWD/../date $ADD_OPTS
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- cmake --build . --config $CONFIG
|
- cmake --build . --config $CONFIG
|
||||||
|
@ -54,18 +54,19 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <std::size_t N, const char (&s)[N], typename T>
|
template <std::size_t N, const char* s, typename T>
|
||||||
struct make_char_sequence_impl;
|
struct make_char_sequence_impl;
|
||||||
|
|
||||||
template <std::size_t N, const char (&s)[N], std::size_t... i>
|
template <std::size_t N, const char* s, std::size_t... i>
|
||||||
struct make_char_sequence_impl<N, s, sqlpp::detail::index_sequence<i...>>
|
struct make_char_sequence_impl<N, s, sqlpp::detail::index_sequence<i...>>
|
||||||
{
|
{
|
||||||
using type = char_sequence<s[i]...>;
|
using type = char_sequence<s[i]...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <std::size_t N, const char (&Input)[N]>
|
template <std::size_t N, const char* Input>
|
||||||
using make_char_sequence =
|
using make_char_sequence =
|
||||||
typename make_char_sequence_impl<N, Input, sqlpp::detail::make_index_sequence<N - 1>>::type;
|
typename make_char_sequence_impl<N, Input, sqlpp::detail::make_index_sequence<N - 1>>::type;
|
||||||
|
|
||||||
} // namespace sqlpp
|
} // namespace sqlpp
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <sqlpp11/data_types/blob/data_type.h>
|
#include <sqlpp11/data_types/blob/data_type.h>
|
||||||
#include <sqlpp11/field_spec.h>
|
#include <sqlpp11/field_spec.h>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
@ -76,7 +77,9 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return os << e.value();
|
std::vector<uint8_t> value = e.value();
|
||||||
|
std::string value_str(value.begin(), value.end());
|
||||||
|
return os << value_str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace sqlpp
|
} // namespace sqlpp
|
||||||
|
@ -29,6 +29,9 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
#include <sqlpp11/alias_operators.h>
|
#include <sqlpp11/alias_operators.h>
|
||||||
#include <sqlpp11/serializer.h>
|
#include <sqlpp11/serializer.h>
|
||||||
@ -50,6 +53,16 @@ namespace sqlpp
|
|||||||
text_operand(_value_t t) : _t(std::move(t))
|
text_operand(_value_t t) : _t(std::move(t))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
// allow construction from an std::string_view
|
||||||
|
text_operand(std::string_view t) : _t(t)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
// additional const char* overload, required to disambiguate
|
||||||
|
text_operand(const char* t) : _t(t)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
text_operand(const text_operand&) = default;
|
text_operand(const text_operand&) = default;
|
||||||
text_operand(text_operand&&) = default;
|
text_operand(text_operand&&) = default;
|
||||||
|
@ -28,6 +28,9 @@
|
|||||||
#define SQLPP11_DATA_TYPES_TEXT_WRAP_OPERAND_H
|
#define SQLPP11_DATA_TYPES_TEXT_WRAP_OPERAND_H
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
#include <sqlpp11/wrap_operand.h>
|
#include <sqlpp11/wrap_operand.h>
|
||||||
|
|
||||||
@ -35,10 +38,16 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
struct text_operand;
|
struct text_operand;
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
using checked_type = std::string_view;
|
||||||
|
#else
|
||||||
|
using checked_type = std::string;
|
||||||
|
#endif
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct wrap_operand<
|
struct wrap_operand<
|
||||||
T,
|
T,
|
||||||
typename std::enable_if<std::is_convertible<T, std::string>::value and not is_result_field_t<T>::value>::type>
|
typename std::enable_if<std::is_convertible<T, checked_type>::value and not is_result_field_t<T>::value>::type>
|
||||||
{
|
{
|
||||||
using type = text_operand;
|
using type = text_operand;
|
||||||
};
|
};
|
||||||
|
@ -102,7 +102,7 @@ namespace sqlpp
|
|||||||
template <typename Expression>
|
template <typename Expression>
|
||||||
void _add_impl(Expression expression, const std::true_type& /*unused*/)
|
void _add_impl(Expression expression, const std::true_type& /*unused*/)
|
||||||
{
|
{
|
||||||
return _data._dynamic_expressions.emplace_back(expression);
|
_data._dynamic_expressions.emplace_back(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Expression>
|
template <typename Expression>
|
||||||
|
@ -103,7 +103,7 @@ namespace sqlpp
|
|||||||
template <typename Expr>
|
template <typename Expr>
|
||||||
void _add_impl(Expr expression, const std::true_type& /*unused*/)
|
void _add_impl(Expr expression, const std::true_type& /*unused*/)
|
||||||
{
|
{
|
||||||
return _data._dynamic_expressions.emplace_back(expression);
|
_data._dynamic_expressions.emplace_back(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Expr>
|
template <typename Expr>
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <sqlpp11/default_value.h>
|
#include <sqlpp11/default_value.h>
|
||||||
#include <sqlpp11/null.h>
|
#include <sqlpp11/null.h>
|
||||||
#include <sqlpp11/tvin.h>
|
#include <sqlpp11/tvin.h>
|
||||||
|
#include <sqlpp11/value_or_null.h>
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
#include <sqlpp11/serializer.h>
|
#include <sqlpp11/serializer.h>
|
||||||
#include <sqlpp11/detail/type_set.h>
|
#include <sqlpp11/detail/type_set.h>
|
||||||
@ -64,6 +65,7 @@ namespace sqlpp
|
|||||||
using _pure_value_t = typename value_type_of<Column>::_cpp_value_type;
|
using _pure_value_t = typename value_type_of<Column>::_cpp_value_type;
|
||||||
using _wrapped_value_t = wrap_operand_t<_pure_value_t>;
|
using _wrapped_value_t = wrap_operand_t<_pure_value_t>;
|
||||||
using _tvin_t = tvin_t<_wrapped_value_t>;
|
using _tvin_t = tvin_t<_wrapped_value_t>;
|
||||||
|
using _value_or_null_t = value_or_null_t<typename Column::_traits::_value_type>;
|
||||||
|
|
||||||
insert_value_t(rhs_wrap_t<_wrapped_value_t, _trivial_value_is_null> rhs)
|
insert_value_t(rhs_wrap_t<_wrapped_value_t, _trivial_value_is_null> rhs)
|
||||||
: _is_null(rhs._is_null()), _is_default(rhs._is_default()), _value(rhs._expr._t)
|
: _is_null(rhs._is_null()), _is_default(rhs._is_default()), _value(rhs._expr._t)
|
||||||
@ -85,6 +87,11 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
insert_value_t(const rhs_wrap_t<_value_or_null_t, _trivial_value_is_null>& rhs)
|
||||||
|
: _is_null(rhs._expr._is_null), _is_default(false), _value{rhs._expr._value}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
insert_value_t(const insert_value_t&) = default;
|
insert_value_t(const insert_value_t&) = default;
|
||||||
insert_value_t(insert_value_t&&) = default;
|
insert_value_t(insert_value_t&&) = default;
|
||||||
insert_value_t& operator=(const insert_value_t&) = default;
|
insert_value_t& operator=(const insert_value_t&) = default;
|
||||||
|
@ -627,17 +627,17 @@ namespace sqlpp
|
|||||||
context << " (";
|
context << " (";
|
||||||
interpret_tuple(t._columns, ",", context);
|
interpret_tuple(t._columns, ",", context);
|
||||||
context << ")";
|
context << ")";
|
||||||
context << " VALUES ";
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (const auto& row : t._insert_values)
|
for (const auto& row : t._insert_values)
|
||||||
{
|
{
|
||||||
if (not first)
|
if (first)
|
||||||
{
|
{
|
||||||
context << ',';
|
context << " VALUES ";
|
||||||
|
first = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
first = false;
|
context << ',';
|
||||||
}
|
}
|
||||||
context << '(';
|
context << '(';
|
||||||
interpret_tuple(row, ",", context);
|
interpret_tuple(row, ",", context);
|
||||||
@ -669,7 +669,10 @@ namespace sqlpp
|
|||||||
context << ',';
|
context << ',';
|
||||||
}
|
}
|
||||||
interpret_list(t._dynamic_columns, ',', context);
|
interpret_list(t._dynamic_columns, ',', context);
|
||||||
context << ") VALUES(";
|
context << ")";
|
||||||
|
if (sizeof...(Assignments) or not t._dynamic_values.empty())
|
||||||
|
{
|
||||||
|
context << " VALUES(";
|
||||||
interpret_tuple(t._values, ",", context);
|
interpret_tuple(t._values, ",", context);
|
||||||
if (sizeof...(Assignments) and not t._dynamic_values.empty())
|
if (sizeof...(Assignments) and not t._dynamic_values.empty())
|
||||||
{
|
{
|
||||||
@ -678,6 +681,7 @@ namespace sqlpp
|
|||||||
interpret_list(t._dynamic_values, ',', context);
|
interpret_list(t._dynamic_values, ',', context);
|
||||||
context << ")";
|
context << ")";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -100,7 +100,7 @@ namespace sqlpp
|
|||||||
template <typename Expression>
|
template <typename Expression>
|
||||||
void _add_impl(Expression expression, const std::true_type& /*unused*/)
|
void _add_impl(Expression expression, const std::true_type& /*unused*/)
|
||||||
{
|
{
|
||||||
return _data._dynamic_expressions.emplace_back(expression);
|
_data._dynamic_expressions.emplace_back(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Expression>
|
template <typename Expression>
|
||||||
|
@ -147,7 +147,7 @@ namespace sqlpp
|
|||||||
template <typename NamedExpression>
|
template <typename NamedExpression>
|
||||||
void _add_impl(NamedExpression namedExpression, const std::true_type& /*unused*/)
|
void _add_impl(NamedExpression namedExpression, const std::true_type& /*unused*/)
|
||||||
{
|
{
|
||||||
return _data._dynamic_columns.emplace_back(auto_alias_t<NamedExpression>{namedExpression});
|
_data._dynamic_columns.emplace_back(auto_alias_t<NamedExpression>{namedExpression});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename NamedExpression>
|
template <typename NamedExpression>
|
||||||
|
@ -96,7 +96,7 @@ namespace sqlpp
|
|||||||
template <typename Flag>
|
template <typename Flag>
|
||||||
void _add_impl(Flag flag, const std::true_type& /*unused*/)
|
void _add_impl(Flag flag, const std::true_type& /*unused*/)
|
||||||
{
|
{
|
||||||
return _data._dynamic_flags.emplace_back(flag);
|
_data._dynamic_flags.emplace_back(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Flag>
|
template <typename Flag>
|
||||||
|
@ -52,7 +52,7 @@ namespace sqlpp
|
|||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _provided_tables = detail::type_set<Table>;
|
using _provided_tables = detail::type_set<Table>;
|
||||||
|
|
||||||
static_assert(sizeof...(ColumnSpec), "at least one column required per table");
|
static_assert(sizeof...(ColumnSpec) > 0, "at least one column required per table");
|
||||||
using _required_insert_columns =
|
using _required_insert_columns =
|
||||||
typename detail::make_type_set_if<require_insert_t, column_t<Table, ColumnSpec>...>::type;
|
typename detail::make_type_set_if<require_insert_t, column_t<Table, ColumnSpec>...>::type;
|
||||||
using _column_tuple_t = std::tuple<column_t<Table, ColumnSpec>...>;
|
using _column_tuple_t = std::tuple<column_t<Table, ColumnSpec>...>;
|
||||||
|
@ -100,7 +100,7 @@ namespace sqlpp
|
|||||||
template <typename Assignment>
|
template <typename Assignment>
|
||||||
void _add_impl(Assignment assignment, const std::true_type& /*unused*/)
|
void _add_impl(Assignment assignment, const std::true_type& /*unused*/)
|
||||||
{
|
{
|
||||||
return _data._dynamic_assignments.emplace_back(assignment);
|
_data._dynamic_assignments.emplace_back(assignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Assignment>
|
template <typename Assignment>
|
||||||
|
@ -92,7 +92,7 @@ namespace sqlpp
|
|||||||
template <typename Table>
|
template <typename Table>
|
||||||
void _add_impl(Table table, const std::true_type& /*unused*/)
|
void _add_impl(Table table, const std::true_type& /*unused*/)
|
||||||
{
|
{
|
||||||
return _data._dynamic_tables.emplace_back(table);
|
_data._dynamic_tables.emplace_back(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Table>
|
template <typename Table>
|
||||||
|
@ -105,7 +105,7 @@ namespace sqlpp
|
|||||||
template <typename Expr>
|
template <typename Expr>
|
||||||
void _add_impl(Expr expression, const std::true_type& /*unused*/)
|
void _add_impl(Expr expression, const std::true_type& /*unused*/)
|
||||||
{
|
{
|
||||||
return _data._dynamic_expressions.emplace_back(expression);
|
_data._dynamic_expressions.emplace_back(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Expr>
|
template <typename Expr>
|
||||||
|
@ -85,6 +85,26 @@ def usage(optionalArgs = {}):
|
|||||||
Usage: ddl2cpp <path to ddl> <path to target (without extension, e.g. /tmp/MyTable)> <namespace>\n\
|
Usage: ddl2cpp <path to ddl> <path to target (without extension, e.g. /tmp/MyTable)> <namespace>\n\
|
||||||
ddl2cpp -help')
|
ddl2cpp -help')
|
||||||
|
|
||||||
|
def beginHeader(pathToHeader, nsList):
|
||||||
|
header = open(pathToHeader, 'w')
|
||||||
|
print('// generated by ' + ' '.join(sys.argv), file=header)
|
||||||
|
print('#ifndef '+get_include_guard_name(namespace, pathToHeader), file=header)
|
||||||
|
print('#define '+get_include_guard_name(namespace, pathToHeader), file=header)
|
||||||
|
print('', file=header)
|
||||||
|
print('#include <' + INCLUDE + '/table.h>', file=header)
|
||||||
|
print('#include <' + INCLUDE + '/data_types.h>', file=header)
|
||||||
|
print('#include <' + INCLUDE + '/char_sequence.h>', file=header)
|
||||||
|
print('', file=header)
|
||||||
|
for ns in nsList:
|
||||||
|
print('namespace ' + ns, file=header)
|
||||||
|
print('{', file=header)
|
||||||
|
return header
|
||||||
|
|
||||||
|
def endHeader(header, nsList):
|
||||||
|
for ns in nsList:
|
||||||
|
print('} // namespace ' + ns, file=header)
|
||||||
|
print('#endif', file=header)
|
||||||
|
header.close()
|
||||||
|
|
||||||
def help_message():
|
def help_message():
|
||||||
arg_string = '\n'
|
arg_string = '\n'
|
||||||
@ -117,7 +137,8 @@ optionalArgs = {
|
|||||||
'-fail-on-parse': "abort instead of silent genereation of unusable headers", # failOnParse = True
|
'-fail-on-parse': "abort instead of silent genereation of unusable headers", # failOnParse = True
|
||||||
'-warn-on-parse': "warn about unusable headers, but continue", # warnOnParse = True
|
'-warn-on-parse': "warn about unusable headers, but continue", # warnOnParse = True
|
||||||
'-auto-id': "Assume column 'id' to have an automatic value as if AUTO_INCREMENT was specified (e.g. implicit for SQLite ROWID)", # autoId = True
|
'-auto-id': "Assume column 'id' to have an automatic value as if AUTO_INCREMENT was specified (e.g. implicit for SQLite ROWID)", # autoId = True
|
||||||
'-identity-naming': "Use table and column names from the ddl (defaults to UpperCamelCase for tables and lowerCamelCase for columns", # identityNaming = True
|
'-identity-naming': "Use table and column names from the ddl (defaults to UpperCamelCase for tables and lowerCamelCase for columns)", # identityNaming = True
|
||||||
|
'-split-tables': "Make a header for each table name, using target as a directory", # splitTables = True
|
||||||
'-help': "show this help"
|
'-help': "show this help"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,6 +156,7 @@ warnOnParse = False
|
|||||||
parseError = "Parsing error, possible reason: can't parse default value for a field"
|
parseError = "Parsing error, possible reason: can't parse default value for a field"
|
||||||
autoId = False
|
autoId = False
|
||||||
identityNaming = False
|
identityNaming = False
|
||||||
|
splitTables = False
|
||||||
|
|
||||||
|
|
||||||
if len(sys.argv) >= 4:
|
if len(sys.argv) >= 4:
|
||||||
@ -155,7 +177,7 @@ if identityNaming:
|
|||||||
|
|
||||||
pathToDdl = sys.argv[firstPositional]
|
pathToDdl = sys.argv[firstPositional]
|
||||||
|
|
||||||
pathToHeader = sys.argv[firstPositional + 1] + '.h'
|
pathToHeader = sys.argv[firstPositional + 1] + ('/' if splitTables else '.h')
|
||||||
namespace = sys.argv[firstPositional + 2]
|
namespace = sys.argv[firstPositional + 2]
|
||||||
|
|
||||||
|
|
||||||
@ -193,6 +215,7 @@ ddlNotNull = Group(ddlWord("NOT") + ddlWord("NULL")).setResultsName("notNull")
|
|||||||
ddlDefaultValue = ddlWord("DEFAULT").setResultsName("hasDefaultValue")
|
ddlDefaultValue = ddlWord("DEFAULT").setResultsName("hasDefaultValue")
|
||||||
ddlAutoValue = Or([
|
ddlAutoValue = Or([
|
||||||
ddlWord("AUTO_INCREMENT"),
|
ddlWord("AUTO_INCREMENT"),
|
||||||
|
ddlWord("AUTOINCREMENT"),
|
||||||
ddlWord("SMALLSERIAL"),
|
ddlWord("SMALLSERIAL"),
|
||||||
ddlWord("SERIAL"),
|
ddlWord("SERIAL"),
|
||||||
ddlWord("BIGSERIAL"),
|
ddlWord("BIGSERIAL"),
|
||||||
@ -246,6 +269,7 @@ types = {
|
|||||||
'float8': 'floating_point', # PostgreSQL
|
'float8': 'floating_point', # PostgreSQL
|
||||||
'float': 'floating_point',
|
'float': 'floating_point',
|
||||||
'float4': 'floating_point', # PostgreSQL
|
'float4': 'floating_point', # PostgreSQL
|
||||||
|
'real': 'floating_point',
|
||||||
'numeric': 'floating_point', # PostgreSQL
|
'numeric': 'floating_point', # PostgreSQL
|
||||||
'date': 'day_point',
|
'date': 'day_point',
|
||||||
'datetime': 'time_point',
|
'datetime': 'time_point',
|
||||||
@ -298,21 +322,14 @@ def escape_if_reserved(name):
|
|||||||
# PROCESS DDL
|
# PROCESS DDL
|
||||||
tableCreations = ddl.parseFile(pathToDdl)
|
tableCreations = ddl.parseFile(pathToDdl)
|
||||||
|
|
||||||
header = open(pathToHeader, 'w')
|
header = 0
|
||||||
print('// generated by ' + ' '.join(sys.argv), file=header)
|
if not splitTables:
|
||||||
print('#ifndef '+get_include_guard_name(namespace, pathToHeader), file=header)
|
header = beginHeader(pathToHeader, nsList)
|
||||||
print('#define '+get_include_guard_name(namespace, pathToHeader), file=header)
|
|
||||||
print('', file=header)
|
|
||||||
print('#include <' + INCLUDE + '/table.h>', file=header)
|
|
||||||
print('#include <' + INCLUDE + '/data_types.h>', file=header)
|
|
||||||
print('#include <' + INCLUDE + '/char_sequence.h>', file=header)
|
|
||||||
print('', file=header)
|
|
||||||
for ns in nsList:
|
|
||||||
print('namespace ' + ns, file=header)
|
|
||||||
print('{', file=header)
|
|
||||||
DataTypeError = False
|
DataTypeError = False
|
||||||
for create in tableCreations:
|
for create in tableCreations:
|
||||||
sqlTableName = create.tableName
|
sqlTableName = create.tableName
|
||||||
|
if splitTables:
|
||||||
|
header = beginHeader(pathToHeader + sqlTableName + '.h', nsList)
|
||||||
tableClass = toClassName(sqlTableName)
|
tableClass = toClassName(sqlTableName)
|
||||||
tableMember = toMemberName(sqlTableName)
|
tableMember = toMemberName(sqlTableName)
|
||||||
tableNamespace = tableClass + '_'
|
tableNamespace = tableClass + '_'
|
||||||
@ -386,10 +403,11 @@ for create in tableCreations:
|
|||||||
print(' };', file=header)
|
print(' };', file=header)
|
||||||
print(' };', file=header)
|
print(' };', file=header)
|
||||||
print(' };', file=header)
|
print(' };', file=header)
|
||||||
|
if splitTables:
|
||||||
|
endHeader(header, nsList)
|
||||||
|
|
||||||
for ns in nsList:
|
if not splitTables:
|
||||||
print('} // namespace ' + ns, file=header)
|
endHeader(header, nsList)
|
||||||
print('#endif', file=header)
|
|
||||||
if (DataTypeError):
|
if (DataTypeError):
|
||||||
print("Error: unsupported datatypes." )
|
print("Error: unsupported datatypes." )
|
||||||
print("Possible solutions:")
|
print("Possible solutions:")
|
||||||
|
199
scripts/sqlite2cpp.py
Normal file
199
scripts/sqlite2cpp.py
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
##
|
||||||
|
# Copyright (c) 2013-2015, Roland Bock
|
||||||
|
# Copyright (c) 2018, Egor Pugin
|
||||||
|
# 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.
|
||||||
|
##
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sqlite3
|
||||||
|
import sys
|
||||||
|
|
||||||
|
INCLUDE = 'sqlpp11'
|
||||||
|
NAMESPACE = 'sqlpp'
|
||||||
|
|
||||||
|
# map sqlite3 types
|
||||||
|
types = {
|
||||||
|
'integer': 'integer',
|
||||||
|
'text': 'text',
|
||||||
|
'blob': 'blob',
|
||||||
|
'real': 'floating_point',
|
||||||
|
}
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description='sqlpp11 cpp schema generator')
|
||||||
|
parser.add_argument('ddl', help='path to ddl')
|
||||||
|
parser.add_argument('target', help='path to target')
|
||||||
|
parser.add_argument('namespace', help='namespace')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
pathToHeader = args.target + '.h'
|
||||||
|
|
||||||
|
# execute schema scripts
|
||||||
|
conn = sqlite3.connect(':memory:')
|
||||||
|
conn.executescript(open(args.ddl).read())
|
||||||
|
|
||||||
|
# set vars
|
||||||
|
toClassName = class_name_naming_func
|
||||||
|
toMemberName = member_name_naming_func
|
||||||
|
DataTypeError = False
|
||||||
|
|
||||||
|
header = open(pathToHeader, 'w')
|
||||||
|
namespace = args.namespace
|
||||||
|
nsList = namespace.split('::')
|
||||||
|
|
||||||
|
# start printing
|
||||||
|
print('// generated by ' + ' '.join(sys.argv), file=header)
|
||||||
|
print('#ifndef '+get_include_guard_name(namespace, pathToHeader), file=header)
|
||||||
|
print('#define '+get_include_guard_name(namespace, pathToHeader), file=header)
|
||||||
|
print('', file=header)
|
||||||
|
print('#include <' + INCLUDE + '/table.h>', file=header)
|
||||||
|
print('#include <' + INCLUDE + '/data_types.h>', file=header)
|
||||||
|
print('#include <' + INCLUDE + '/char_sequence.h>', file=header)
|
||||||
|
print('', file=header)
|
||||||
|
for ns in nsList:
|
||||||
|
print('namespace ' + ns, file=header)
|
||||||
|
print('{', file=header)
|
||||||
|
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
|
||||||
|
tables = cursor.fetchall()
|
||||||
|
for table_name in tables:
|
||||||
|
table_name = table_name[0]
|
||||||
|
|
||||||
|
if table_name.startswith('sqlite_'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
sqlTableName = table_name
|
||||||
|
tableClass = toClassName(sqlTableName)
|
||||||
|
tableMember = toMemberName(sqlTableName)
|
||||||
|
tableNamespace = tableClass + '_'
|
||||||
|
tableTemplateParameters = tableClass
|
||||||
|
print(' namespace ' + tableNamespace, file=header)
|
||||||
|
print(' {', file=header)
|
||||||
|
|
||||||
|
columns = cursor.execute("PRAGMA table_info('%s')" % table_name).fetchall()
|
||||||
|
for column in columns:
|
||||||
|
sqlColumnName = column[1]
|
||||||
|
columnClass = toClassName(sqlColumnName)
|
||||||
|
tableTemplateParameters += ',\n ' + tableNamespace + '::' + columnClass
|
||||||
|
columnMember = toMemberName(sqlColumnName)
|
||||||
|
sqlColumnType = column[2].lower()
|
||||||
|
print(' struct ' + columnClass, file=header)
|
||||||
|
print(' {', file=header)
|
||||||
|
print(' struct _alias_t', file=header)
|
||||||
|
print(' {', file=header)
|
||||||
|
print(' static constexpr const char _literal[] = "' + escape_if_reserved(sqlColumnName) + '";', file=header)
|
||||||
|
print(' using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;', file=header)
|
||||||
|
print(' template<typename T>', file=header)
|
||||||
|
print(' struct _member_t', file=header)
|
||||||
|
print(' {', file=header)
|
||||||
|
print(' T ' + columnMember + ';', file=header)
|
||||||
|
print(' T& operator()() { return ' + columnMember + '; }', file=header)
|
||||||
|
print(' const T& operator()() const { return ' + columnMember + '; }', file=header)
|
||||||
|
print(' };', file=header)
|
||||||
|
print(' };', file=header)
|
||||||
|
try:
|
||||||
|
traitslist = [NAMESPACE + '::' + types[sqlColumnType]]
|
||||||
|
except KeyError as e:
|
||||||
|
print ('Error: datatype "' + sqlColumnType + '"" is not supported.')
|
||||||
|
DataTypeError = True
|
||||||
|
requireInsert = True
|
||||||
|
hasAutoValue = sqlColumnName == 'id'
|
||||||
|
if hasAutoValue:
|
||||||
|
traitslist.append(NAMESPACE + '::tag::must_not_insert')
|
||||||
|
traitslist.append(NAMESPACE + '::tag::must_not_update')
|
||||||
|
requireInsert = False
|
||||||
|
if column[3] == '0':
|
||||||
|
traitslist.append(NAMESPACE + '::tag::can_be_null')
|
||||||
|
requireInsert = False
|
||||||
|
if column[4]:
|
||||||
|
requireInsert = False
|
||||||
|
if requireInsert:
|
||||||
|
traitslist.append(NAMESPACE + '::tag::require_insert')
|
||||||
|
print(' using _traits = ' + NAMESPACE + '::make_traits<' + ', '.join(traitslist) + '>;', file=header)
|
||||||
|
print(' };', file=header)
|
||||||
|
|
||||||
|
print(' } // namespace ' + tableNamespace, file=header)
|
||||||
|
print('', file=header)
|
||||||
|
|
||||||
|
print(' struct ' + tableClass + ': ' + NAMESPACE + '::table_t<' + tableTemplateParameters + '>', file=header)
|
||||||
|
print(' {', file=header)
|
||||||
|
print(' struct _alias_t', file=header)
|
||||||
|
print(' {', file=header)
|
||||||
|
print(' static constexpr const char _literal[] = "' + sqlTableName + '";', file=header)
|
||||||
|
print(' using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;', file=header)
|
||||||
|
print(' template<typename T>', file=header)
|
||||||
|
print(' struct _member_t', file=header)
|
||||||
|
print(' {', file=header)
|
||||||
|
print(' T ' + tableMember + ';', file=header)
|
||||||
|
print(' T& operator()() { return ' + tableMember + '; }', file=header)
|
||||||
|
print(' const T& operator()() const { return ' + tableMember + '; }', file=header)
|
||||||
|
print(' };', file=header)
|
||||||
|
print(' };', file=header)
|
||||||
|
print(' };', file=header)
|
||||||
|
|
||||||
|
|
||||||
|
for ns in nsList:
|
||||||
|
print('} // namespace ' + ns, file=header)
|
||||||
|
print('#endif', file=header)
|
||||||
|
|
||||||
|
if (DataTypeError):
|
||||||
|
print("Error: unsupported datatypes." )
|
||||||
|
print("Possible solutions:")
|
||||||
|
print("A) Implement this datatype (examples: sqlpp11/data_types)" )
|
||||||
|
print("B) Extend/upgrade ddl2cpp (edit types map)" )
|
||||||
|
print("C) Raise an issue on github" )
|
||||||
|
sys.exit(10) #return non-zero error code, we might need it for automation
|
||||||
|
|
||||||
|
def get_include_guard_name(namespace, inputfile):
|
||||||
|
val = re.sub("[^A-Za-z0-9]+", "_", namespace + '_' + os.path.basename(inputfile))
|
||||||
|
return val.upper()
|
||||||
|
|
||||||
|
def repl_camel_case_func(m):
|
||||||
|
if m.group(1) == '_':
|
||||||
|
return m.group(2).upper()
|
||||||
|
else:
|
||||||
|
return m.group(1) + m.group(2).upper()
|
||||||
|
|
||||||
|
def class_name_naming_func(s):
|
||||||
|
return re.sub("(^|\s|[_0-9])(\S)", repl_camel_case_func, s)
|
||||||
|
|
||||||
|
def member_name_naming_func(s):
|
||||||
|
return re.sub("(\s|_|[0-9])(\S)", repl_camel_case_func, s)
|
||||||
|
|
||||||
|
def escape_if_reserved(name):
|
||||||
|
reserved_names = [
|
||||||
|
'GROUP',
|
||||||
|
'ORDER',
|
||||||
|
]
|
||||||
|
if name.upper() in reserved_names:
|
||||||
|
return '!{}'.format(name)
|
||||||
|
return name
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
sys.exit(0)
|
@ -31,6 +31,12 @@ function(test_constraint name pattern)
|
|||||||
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target ${target}
|
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target ${target}
|
||||||
)
|
)
|
||||||
set_property(TEST ${test} PROPERTY PASS_REGULAR_EXPRESSION ${pattern})
|
set_property(TEST ${test} PROPERTY PASS_REGULAR_EXPRESSION ${pattern})
|
||||||
|
# conditionally bump to a higher C++ standard to test compatibility
|
||||||
|
if (SQLPP11_TESTS_CXX_STD)
|
||||||
|
set_property(TARGET ${target} PROPERTY CXX_STANDARD ${SQLPP11_TESTS_CXX_STD})
|
||||||
|
set_property(TARGET ${target} PROPERTY CXX_STANDARD_REQUIRED yes)
|
||||||
|
set_property(TARGET ${target} PROPERTY CXX_EXTENSIONS no)
|
||||||
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
# Compiling these is required to fail (testing some static_assert)
|
# Compiling these is required to fail (testing some static_assert)
|
||||||
|
@ -38,6 +38,13 @@ create_test_sourcelist(test_serializer_sources test_serializer_main.cpp ${test_s
|
|||||||
add_executable(sqlpp11_test_serializer ${test_serializer_sources})
|
add_executable(sqlpp11_test_serializer ${test_serializer_sources})
|
||||||
target_link_libraries(sqlpp11_test_serializer PRIVATE sqlpp11 sqlpp11_testing)
|
target_link_libraries(sqlpp11_test_serializer PRIVATE sqlpp11 sqlpp11_testing)
|
||||||
|
|
||||||
|
# conditionally bump to a higher C++ standard to test compatibility
|
||||||
|
if (SQLPP11_TESTS_CXX_STD)
|
||||||
|
set_property(TARGET sqlpp11_test_serializer PROPERTY CXX_STANDARD ${SQLPP11_TESTS_CXX_STD})
|
||||||
|
set_property(TARGET sqlpp11_test_serializer PROPERTY CXX_STANDARD_REQUIRED yes)
|
||||||
|
set_property(TARGET sqlpp11_test_serializer PROPERTY CXX_EXTENSIONS no)
|
||||||
|
endif()
|
||||||
|
|
||||||
foreach(test_serializer IN LISTS test_serializer_names)
|
foreach(test_serializer IN LISTS test_serializer_names)
|
||||||
add_test(NAME sqlpp11.test_serializer.${test_serializer}
|
add_test(NAME sqlpp11.test_serializer.${test_serializer}
|
||||||
COMMAND sqlpp11_test_serializer ${test_serializer}
|
COMMAND sqlpp11_test_serializer ${test_serializer}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2016, Roland Bock
|
* Copyright (c) 2016-2019, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -38,7 +38,8 @@ int CustomQuery(int, char* [])
|
|||||||
auto db = MockDb{};
|
auto db = MockDb{};
|
||||||
|
|
||||||
// Unconditionally
|
// Unconditionally
|
||||||
compare(__LINE__, custom_query(sqlpp::select(), select_flags(sqlpp::distinct), select_columns(foo.omega), from(foo),
|
compare(__LINE__,
|
||||||
|
custom_query(sqlpp::select(), select_flags(sqlpp::distinct), select_columns(foo.omega), from(foo),
|
||||||
sqlpp::unconditionally()),
|
sqlpp::unconditionally()),
|
||||||
"SELECT DISTINCT tab_foo.omega FROM tab_foo ");
|
"SELECT DISTINCT tab_foo.omega FROM tab_foo ");
|
||||||
|
|
||||||
@ -68,5 +69,16 @@ int CustomQuery(int, char* [])
|
|||||||
custom_query(sqlpp::verbatim("PRAGMA user_version")).with_result_type_of(select(sqlpp::value(1).as(pragma))),
|
custom_query(sqlpp::verbatim("PRAGMA user_version")).with_result_type_of(select(sqlpp::value(1).as(pragma))),
|
||||||
" PRAGMA user_version");
|
" PRAGMA user_version");
|
||||||
|
|
||||||
|
// An insert from select for postgresql
|
||||||
|
const auto x = 17;
|
||||||
|
compare(__LINE__,
|
||||||
|
custom_query(insert_into(foo).columns(foo.omega),
|
||||||
|
select(sqlpp::value(x).as(foo.omega))
|
||||||
|
.from(foo)
|
||||||
|
.where(not exists(select(foo.omega).from(foo).where(foo.omega == x)))),
|
||||||
|
"INSERT INTO tab_foo (omega) "
|
||||||
|
"SELECT 17 AS omega FROM tab_foo "
|
||||||
|
"WHERE (NOT EXISTS(SELECT tab_foo.omega FROM tab_foo WHERE (tab_foo.omega=17)))");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,12 @@ int Insert(int, char* [])
|
|||||||
compare(__LINE__, insert_into(bar).default_values(), "INSERT INTO tab_bar DEFAULT VALUES");
|
compare(__LINE__, insert_into(bar).default_values(), "INSERT INTO tab_bar DEFAULT VALUES");
|
||||||
compare(__LINE__, insert_into(bar).set(bar.beta = "cheesecake", bar.gamma = true),
|
compare(__LINE__, insert_into(bar).set(bar.beta = "cheesecake", bar.gamma = true),
|
||||||
"INSERT INTO tab_bar (beta,gamma) VALUES('cheesecake'," + getTrue() + ")");
|
"INSERT INTO tab_bar (beta,gamma) VALUES('cheesecake'," + getTrue() + ")");
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
// string_view argument
|
||||||
|
std::string_view cheeseCake = "cheesecake";
|
||||||
|
compare(__LINE__, insert_into(bar).set(bar.beta = cheeseCake, bar.gamma = true),
|
||||||
|
"INSERT INTO tab_bar (beta,gamma) VALUES('cheesecake'," + getTrue() + ")");
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,11 @@ int Where(int, char* [])
|
|||||||
compare(__LINE__, where(bar.gamma), " WHERE tab_bar.gamma");
|
compare(__LINE__, where(bar.gamma), " WHERE tab_bar.gamma");
|
||||||
compare(__LINE__, where(bar.gamma == false), " WHERE (tab_bar.gamma=" + getFalse() + ")");
|
compare(__LINE__, where(bar.gamma == false), " WHERE (tab_bar.gamma=" + getFalse() + ")");
|
||||||
compare(__LINE__, where(bar.beta == "SQL"), " WHERE (tab_bar.beta='SQL')");
|
compare(__LINE__, where(bar.beta == "SQL"), " WHERE (tab_bar.beta='SQL')");
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
// string_view argument
|
||||||
|
std::string_view sqlString = "SQL";
|
||||||
|
compare(__LINE__, where(bar.beta == sqlString), " WHERE (tab_bar.beta='SQL')");
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,12 @@ function(test_compile name)
|
|||||||
set(target sqlpp11_assert_${name})
|
set(target sqlpp11_assert_${name})
|
||||||
add_executable(${target} ${name}.cpp)
|
add_executable(${target} ${name}.cpp)
|
||||||
target_link_libraries(${target} PRIVATE sqlpp11 sqlpp11_testing)
|
target_link_libraries(${target} PRIVATE sqlpp11 sqlpp11_testing)
|
||||||
|
# conditionally bump to a higher C++ standard to test compatibility
|
||||||
|
if (SQLPP11_TESTS_CXX_STD)
|
||||||
|
set_property(TARGET sqlpp11_assert_${name} PROPERTY CXX_STANDARD ${SQLPP11_TESTS_CXX_STD})
|
||||||
|
set_property(TARGET sqlpp11_assert_${name} PROPERTY CXX_STANDARD_REQUIRED yes)
|
||||||
|
set_property(TARGET sqlpp11_assert_${name} PROPERTY CXX_EXTENSIONS no)
|
||||||
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
test_compile(aggregates)
|
test_compile(aggregates)
|
||||||
|
@ -26,6 +26,12 @@ function(test_compile name)
|
|||||||
set(target sqlpp11_${name})
|
set(target sqlpp11_${name})
|
||||||
add_executable(${target} ${name}.cpp)
|
add_executable(${target} ${name}.cpp)
|
||||||
target_link_libraries(${target} PRIVATE sqlpp11 sqlpp11_testing)
|
target_link_libraries(${target} PRIVATE sqlpp11 sqlpp11_testing)
|
||||||
|
# conditionally bump to a higher C++ standard to test compatibility
|
||||||
|
if (SQLPP11_TESTS_CXX_STD)
|
||||||
|
set_property(TARGET sqlpp11_${name} PROPERTY CXX_STANDARD ${SQLPP11_TESTS_CXX_STD})
|
||||||
|
set_property(TARGET sqlpp11_${name} PROPERTY CXX_STANDARD_REQUIRED yes)
|
||||||
|
set_property(TARGET sqlpp11_${name} PROPERTY CXX_EXTENSIONS no)
|
||||||
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
test_compile(result_row)
|
test_compile(result_row)
|
||||||
|
@ -34,6 +34,7 @@ int BooleanExpression(int, char* [])
|
|||||||
const auto t = test::TabBar{};
|
const auto t = test::TabBar{};
|
||||||
|
|
||||||
auto x = boolean_expression(db, not(t.alpha == 7));
|
auto x = boolean_expression(db, not(t.alpha == 7));
|
||||||
|
x = sqlpp::boolean_expression(db, true);
|
||||||
x = sqlpp::boolean_expression<MockDb>(t.beta.like("%cheesecake"));
|
x = sqlpp::boolean_expression<MockDb>(t.beta.like("%cheesecake"));
|
||||||
x = x and boolean_expression(db, t.gamma);
|
x = x and boolean_expression(db, t.gamma);
|
||||||
|
|
||||||
|
@ -57,6 +57,12 @@ endif()
|
|||||||
create_test_sourcelist(test_sources test_main.cpp ${test_names})
|
create_test_sourcelist(test_sources test_main.cpp ${test_names})
|
||||||
add_executable(sqlpp11_tests ${test_sources})
|
add_executable(sqlpp11_tests ${test_sources})
|
||||||
target_link_libraries(sqlpp11_tests PRIVATE sqlpp11 sqlpp11_testing)
|
target_link_libraries(sqlpp11_tests PRIVATE sqlpp11 sqlpp11_testing)
|
||||||
|
# conditionally bump to a higher C++ standard to test compatibility
|
||||||
|
if (SQLPP11_TESTS_CXX_STD)
|
||||||
|
set_property(TARGET sqlpp11_tests PROPERTY CXX_STANDARD ${SQLPP11_TESTS_CXX_STD})
|
||||||
|
set_property(TARGET sqlpp11_tests PROPERTY CXX_STANDARD_REQUIRED yes)
|
||||||
|
set_property(TARGET sqlpp11_tests PROPERTY CXX_EXTENSIONS no)
|
||||||
|
endif()
|
||||||
|
|
||||||
foreach(test IN LISTS test_names)
|
foreach(test IN LISTS test_names)
|
||||||
add_test(NAME sqlpp11.tests.${test}
|
add_test(NAME sqlpp11.tests.${test}
|
||||||
|
@ -29,6 +29,34 @@
|
|||||||
#include <sqlpp11/sqlpp11.h>
|
#include <sqlpp11/sqlpp11.h>
|
||||||
#include <sqlpp11/custom_query.h>
|
#include <sqlpp11/custom_query.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct on_duplicate_key_update
|
||||||
|
{
|
||||||
|
std::string _serialized;
|
||||||
|
|
||||||
|
template <typename Db, typename Assignment>
|
||||||
|
on_duplicate_key_update(Db&, Assignment assignment)
|
||||||
|
{
|
||||||
|
typename Db::_serializer_context_t context;
|
||||||
|
_serialized = " ON DUPLICATE KEY UPDATE " + serialize(assignment, context).str();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Db, typename Assignment>
|
||||||
|
auto operator()(Db&, Assignment assignment) -> on_duplicate_key_update&
|
||||||
|
{
|
||||||
|
typename Db::_serializer_context_t context;
|
||||||
|
_serialized += ", " + serialize(assignment, context).str();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto get() const -> sqlpp::verbatim_t<::sqlpp::no_value_t>
|
||||||
|
{
|
||||||
|
return ::sqlpp::verbatim(_serialized);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
int CustomQuery(int, char*[])
|
int CustomQuery(int, char*[])
|
||||||
{
|
{
|
||||||
MockDb db = {};
|
MockDb db = {};
|
||||||
@ -61,6 +89,10 @@ int CustomQuery(int, char* [])
|
|||||||
db(custom_query(sqlpp::insert(), sqlpp::verbatim(" OR IGNORE"), into(t),
|
db(custom_query(sqlpp::insert(), sqlpp::verbatim(" OR IGNORE"), into(t),
|
||||||
insert_set(t.beta = "sample", t.gamma = true)));
|
insert_set(t.beta = "sample", t.gamma = true)));
|
||||||
|
|
||||||
|
// Create a MYSQL style custom "insert on duplicate update"
|
||||||
|
db(custom_query(sqlpp::insert_into(t).set(t.beta = "sample", t.gamma = true),
|
||||||
|
on_duplicate_key_update(db, t.beta = "sample")(db, t.gamma = false).get()));
|
||||||
|
|
||||||
// A custom (select ... into) with adjusted return type
|
// A custom (select ... into) with adjusted return type
|
||||||
// The first argument with a return type is the select, but the custom query is really an insert. Thus, we tell it so.
|
// The first argument with a return type is the select, but the custom query is really an insert. Thus, we tell it so.
|
||||||
printer.reset();
|
printer.reset();
|
||||||
@ -69,6 +101,10 @@ int CustomQuery(int, char* [])
|
|||||||
auto i = db(c);
|
auto i = db(c);
|
||||||
static_assert(std::is_integral<decltype(i)>::value, "insert yields an integral value");
|
static_assert(std::is_integral<decltype(i)>::value, "insert yields an integral value");
|
||||||
|
|
||||||
|
auto d = custom_query(sqlpp::verbatim("INSERT INTO tab_sample VALUES()")).with_result_type_of(sqlpp::insert());
|
||||||
|
auto j = db(d);
|
||||||
|
static_assert(std::is_integral<decltype(j)>::value, "insert yields an integral value");
|
||||||
|
|
||||||
for (const auto& row :
|
for (const auto& row :
|
||||||
db(custom_query(sqlpp::verbatim("PRAGMA user_version")).with_result_type_of(select(all_of(t)))))
|
db(custom_query(sqlpp::verbatim("PRAGMA user_version")).with_result_type_of(select(all_of(t)))))
|
||||||
{
|
{
|
||||||
|
@ -51,6 +51,8 @@ int DateTime(int, char* [])
|
|||||||
{
|
{
|
||||||
std::cout << row.colDayPoint;
|
std::cout << row.colDayPoint;
|
||||||
std::cout << row.colTimePoint;
|
std::cout << row.colTimePoint;
|
||||||
|
const auto tp = std::chrono::system_clock::time_point{row.colTimePoint.value()};
|
||||||
|
std::cout << std::chrono::system_clock::to_time_t(tp);
|
||||||
}
|
}
|
||||||
printer.reset();
|
printer.reset();
|
||||||
std::cerr << serialize(::sqlpp::value(std::chrono::system_clock::now()), printer).str() << std::endl;
|
std::cerr << serialize(::sqlpp::value(std::chrono::system_clock::now()), printer).str() << std::endl;
|
||||||
|
@ -352,9 +352,9 @@ int Function(int, char* [])
|
|||||||
using TT = decltype(sqlpp::value("cheesecake"));
|
using TT = decltype(sqlpp::value("cheesecake"));
|
||||||
static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
|
static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
|
||||||
static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement");
|
static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement");
|
||||||
static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
|
|
||||||
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
|
|
||||||
static_assert(not sqlpp::is_selectable_t<TI>::value, "type requirement");
|
static_assert(not sqlpp::is_selectable_t<TI>::value, "type requirement");
|
||||||
|
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
|
||||||
|
static_assert(not sqlpp::is_selectable_t<TF>::value, "type requirement");
|
||||||
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
|
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
|
||||||
static_assert(not sqlpp::is_selectable_t<TT>::value, "type requirement");
|
static_assert(not sqlpp::is_selectable_t<TT>::value, "type requirement");
|
||||||
static_assert(sqlpp::is_text_t<TT>::value, "type requirement");
|
static_assert(sqlpp::is_text_t<TT>::value, "type requirement");
|
||||||
@ -368,9 +368,9 @@ int Function(int, char* [])
|
|||||||
using TT = decltype(flatten(t.beta, db));
|
using TT = decltype(flatten(t.beta, db));
|
||||||
static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
|
static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
|
||||||
static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement");
|
static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement");
|
||||||
static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
|
|
||||||
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
|
|
||||||
static_assert(not sqlpp::is_selectable_t<TI>::value, "type requirement");
|
static_assert(not sqlpp::is_selectable_t<TI>::value, "type requirement");
|
||||||
|
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
|
||||||
|
static_assert(not sqlpp::is_selectable_t<TF>::value, "type requirement");
|
||||||
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
|
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
|
||||||
static_assert(not sqlpp::is_selectable_t<TT>::value, "type requirement");
|
static_assert(not sqlpp::is_selectable_t<TT>::value, "type requirement");
|
||||||
static_assert(sqlpp::is_text_t<TT>::value, "type requirement");
|
static_assert(sqlpp::is_text_t<TT>::value, "type requirement");
|
||||||
@ -392,9 +392,9 @@ int Function(int, char* [])
|
|||||||
static_assert(std::is_same<TT, TTN>::value, "type_requirement");
|
static_assert(std::is_same<TT, TTN>::value, "type_requirement");
|
||||||
static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
|
static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
|
||||||
static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement");
|
static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement");
|
||||||
static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
|
|
||||||
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
|
|
||||||
static_assert(not sqlpp::is_selectable_t<TI>::value, "type requirement");
|
static_assert(not sqlpp::is_selectable_t<TI>::value, "type requirement");
|
||||||
|
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
|
||||||
|
static_assert(not sqlpp::is_selectable_t<TF>::value, "type requirement");
|
||||||
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
|
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
|
||||||
static_assert(not sqlpp::is_selectable_t<TT>::value, "type requirement");
|
static_assert(not sqlpp::is_selectable_t<TT>::value, "type requirement");
|
||||||
static_assert(sqlpp::is_text_t<TT>::value, "type requirement");
|
static_assert(sqlpp::is_text_t<TT>::value, "type requirement");
|
||||||
@ -411,9 +411,9 @@ int Function(int, char* [])
|
|||||||
static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement");
|
static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement");
|
||||||
static_assert(sqlpp::is_selectable_t<TBS>::value, "type requirement");
|
static_assert(sqlpp::is_selectable_t<TBS>::value, "type requirement");
|
||||||
static_assert(sqlpp::is_boolean_t<TBS>::value, "type requirement");
|
static_assert(sqlpp::is_boolean_t<TBS>::value, "type requirement");
|
||||||
static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
|
|
||||||
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
|
|
||||||
static_assert(not sqlpp::is_selectable_t<TI>::value, "type requirement");
|
static_assert(not sqlpp::is_selectable_t<TI>::value, "type requirement");
|
||||||
|
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
|
||||||
|
static_assert(not sqlpp::is_selectable_t<TF>::value, "type requirement");
|
||||||
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
|
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
|
||||||
static_assert(not sqlpp::is_selectable_t<TT>::value, "type requirement");
|
static_assert(not sqlpp::is_selectable_t<TT>::value, "type requirement");
|
||||||
static_assert(sqlpp::is_text_t<TT>::value, "type requirement");
|
static_assert(sqlpp::is_text_t<TT>::value, "type requirement");
|
||||||
|
@ -54,6 +54,8 @@ int Insert(int, char*[])
|
|||||||
|
|
||||||
db(insert_into(t).default_values());
|
db(insert_into(t).default_values());
|
||||||
db(insert_into(t).set(t.gamma = true, t.beta = "kirschauflauf"));
|
db(insert_into(t).set(t.gamma = true, t.beta = "kirschauflauf"));
|
||||||
|
db(insert_into(t).set(t.gamma = sqlpp::default_value, t.beta = sqlpp::value_or_null("pie"),
|
||||||
|
t.delta = sqlpp::value_or_null<sqlpp::integer>(sqlpp::null)));
|
||||||
|
|
||||||
serialize(insert_into(t).default_values(), printer).str();
|
serialize(insert_into(t).default_values(), printer).str();
|
||||||
|
|
||||||
@ -64,6 +66,11 @@ int Insert(int, char*[])
|
|||||||
multi_insert.values.add(t.gamma = true, t.beta = "cheesecake", t.delta = 1);
|
multi_insert.values.add(t.gamma = true, t.beta = "cheesecake", t.delta = 1);
|
||||||
multi_insert.values.add(t.gamma = sqlpp::default_value, t.beta = sqlpp::default_value,
|
multi_insert.values.add(t.gamma = sqlpp::default_value, t.beta = sqlpp::default_value,
|
||||||
t.delta = sqlpp::default_value);
|
t.delta = sqlpp::default_value);
|
||||||
|
multi_insert.values.add(t.gamma = sqlpp::value_or_null(true), t.beta = sqlpp::value_or_null("pie"),
|
||||||
|
t.delta = sqlpp::value_or_null<sqlpp::integer>(sqlpp::null));
|
||||||
|
printer.reset();
|
||||||
|
std::cerr << serialize(multi_insert, printer).str() << std::endl;
|
||||||
|
|
||||||
auto i = dynamic_insert_into(db, t).dynamic_set();
|
auto i = dynamic_insert_into(db, t).dynamic_set();
|
||||||
i.insert_list.add(t.beta = "kirschauflauf");
|
i.insert_list.add(t.beta = "kirschauflauf");
|
||||||
printer.reset();
|
printer.reset();
|
||||||
|
Loading…
Reference in New Issue
Block a user