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:
|
||||
- CONFIG=Release
|
||||
- CONFIG=Release TESTS_CXX_STD=17
|
||||
#- CONFIG=Debug
|
||||
|
||||
notifications:
|
||||
@ -37,7 +38,8 @@ before_script:
|
||||
sudo apt-get install python-pyparsing;
|
||||
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:
|
||||
- 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;
|
||||
|
||||
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...>>
|
||||
{
|
||||
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 =
|
||||
typename make_char_sequence_impl<N, Input, sqlpp::detail::make_index_sequence<N - 1>>::type;
|
||||
|
||||
} // namespace sqlpp
|
||||
|
||||
#endif
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <sqlpp11/data_types/blob/data_type.h>
|
||||
#include <sqlpp11/field_spec.h>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
@ -76,7 +77,9 @@ namespace sqlpp
|
||||
}
|
||||
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
|
||||
|
@ -29,6 +29,9 @@
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#if __cplusplus >= 201703L
|
||||
#include <string_view>
|
||||
#endif
|
||||
#include <sqlpp11/type_traits.h>
|
||||
#include <sqlpp11/alias_operators.h>
|
||||
#include <sqlpp11/serializer.h>
|
||||
@ -50,6 +53,16 @@ namespace sqlpp
|
||||
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(text_operand&&) = default;
|
||||
|
@ -28,6 +28,9 @@
|
||||
#define SQLPP11_DATA_TYPES_TEXT_WRAP_OPERAND_H
|
||||
|
||||
#include <utility>
|
||||
#if __cplusplus >= 201703L
|
||||
#include <string_view>
|
||||
#endif
|
||||
#include <sqlpp11/type_traits.h>
|
||||
#include <sqlpp11/wrap_operand.h>
|
||||
|
||||
@ -35,10 +38,16 @@ namespace sqlpp
|
||||
{
|
||||
struct text_operand;
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
using checked_type = std::string_view;
|
||||
#else
|
||||
using checked_type = std::string;
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct wrap_operand<
|
||||
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;
|
||||
};
|
||||
|
@ -102,7 +102,7 @@ namespace sqlpp
|
||||
template <typename Expression>
|
||||
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>
|
||||
|
@ -103,7 +103,7 @@ namespace sqlpp
|
||||
template <typename Expr>
|
||||
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>
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <sqlpp11/default_value.h>
|
||||
#include <sqlpp11/null.h>
|
||||
#include <sqlpp11/tvin.h>
|
||||
#include <sqlpp11/value_or_null.h>
|
||||
#include <sqlpp11/type_traits.h>
|
||||
#include <sqlpp11/serializer.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 _wrapped_value_t = wrap_operand_t<_pure_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)
|
||||
: _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(insert_value_t&&) = default;
|
||||
insert_value_t& operator=(const insert_value_t&) = default;
|
||||
|
@ -627,17 +627,17 @@ namespace sqlpp
|
||||
context << " (";
|
||||
interpret_tuple(t._columns, ",", context);
|
||||
context << ")";
|
||||
context << " VALUES ";
|
||||
bool first = true;
|
||||
for (const auto& row : t._insert_values)
|
||||
{
|
||||
if (not first)
|
||||
if (first)
|
||||
{
|
||||
context << ',';
|
||||
context << " VALUES ";
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
first = false;
|
||||
context << ',';
|
||||
}
|
||||
context << '(';
|
||||
interpret_tuple(row, ",", context);
|
||||
@ -669,7 +669,10 @@ namespace sqlpp
|
||||
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);
|
||||
if (sizeof...(Assignments) and not t._dynamic_values.empty())
|
||||
{
|
||||
@ -678,6 +681,7 @@ namespace sqlpp
|
||||
interpret_list(t._dynamic_values, ',', context);
|
||||
context << ")";
|
||||
}
|
||||
}
|
||||
return context;
|
||||
}
|
||||
};
|
||||
|
@ -100,7 +100,7 @@ namespace sqlpp
|
||||
template <typename Expression>
|
||||
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>
|
||||
|
@ -147,7 +147,7 @@ namespace sqlpp
|
||||
template <typename NamedExpression>
|
||||
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>
|
||||
|
@ -96,7 +96,7 @@ namespace sqlpp
|
||||
template <typename Flag>
|
||||
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>
|
||||
|
@ -52,7 +52,7 @@ namespace sqlpp
|
||||
using _nodes = detail::type_vector<>;
|
||||
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 =
|
||||
typename detail::make_type_set_if<require_insert_t, column_t<Table, ColumnSpec>...>::type;
|
||||
using _column_tuple_t = std::tuple<column_t<Table, ColumnSpec>...>;
|
||||
|
@ -100,7 +100,7 @@ namespace sqlpp
|
||||
template <typename Assignment>
|
||||
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>
|
||||
|
@ -92,7 +92,7 @@ namespace sqlpp
|
||||
template <typename Table>
|
||||
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>
|
||||
|
@ -105,7 +105,7 @@ namespace sqlpp
|
||||
template <typename Expr>
|
||||
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>
|
||||
|
@ -85,6 +85,26 @@ def usage(optionalArgs = {}):
|
||||
Usage: ddl2cpp <path to ddl> <path to target (without extension, e.g. /tmp/MyTable)> <namespace>\n\
|
||||
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():
|
||||
arg_string = '\n'
|
||||
@ -117,7 +137,8 @@ optionalArgs = {
|
||||
'-fail-on-parse': "abort instead of silent genereation of unusable headers", # failOnParse = 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
|
||||
'-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"
|
||||
}
|
||||
|
||||
@ -135,6 +156,7 @@ warnOnParse = False
|
||||
parseError = "Parsing error, possible reason: can't parse default value for a field"
|
||||
autoId = False
|
||||
identityNaming = False
|
||||
splitTables = False
|
||||
|
||||
|
||||
if len(sys.argv) >= 4:
|
||||
@ -155,7 +177,7 @@ if identityNaming:
|
||||
|
||||
pathToDdl = sys.argv[firstPositional]
|
||||
|
||||
pathToHeader = sys.argv[firstPositional + 1] + '.h'
|
||||
pathToHeader = sys.argv[firstPositional + 1] + ('/' if splitTables else '.h')
|
||||
namespace = sys.argv[firstPositional + 2]
|
||||
|
||||
|
||||
@ -193,6 +215,7 @@ ddlNotNull = Group(ddlWord("NOT") + ddlWord("NULL")).setResultsName("notNull")
|
||||
ddlDefaultValue = ddlWord("DEFAULT").setResultsName("hasDefaultValue")
|
||||
ddlAutoValue = Or([
|
||||
ddlWord("AUTO_INCREMENT"),
|
||||
ddlWord("AUTOINCREMENT"),
|
||||
ddlWord("SMALLSERIAL"),
|
||||
ddlWord("SERIAL"),
|
||||
ddlWord("BIGSERIAL"),
|
||||
@ -246,6 +269,7 @@ types = {
|
||||
'float8': 'floating_point', # PostgreSQL
|
||||
'float': 'floating_point',
|
||||
'float4': 'floating_point', # PostgreSQL
|
||||
'real': 'floating_point',
|
||||
'numeric': 'floating_point', # PostgreSQL
|
||||
'date': 'day_point',
|
||||
'datetime': 'time_point',
|
||||
@ -298,21 +322,14 @@ def escape_if_reserved(name):
|
||||
# PROCESS DDL
|
||||
tableCreations = ddl.parseFile(pathToDdl)
|
||||
|
||||
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)
|
||||
header = 0
|
||||
if not splitTables:
|
||||
header = beginHeader(pathToHeader, nsList)
|
||||
DataTypeError = False
|
||||
for create in tableCreations:
|
||||
sqlTableName = create.tableName
|
||||
if splitTables:
|
||||
header = beginHeader(pathToHeader + sqlTableName + '.h', nsList)
|
||||
tableClass = toClassName(sqlTableName)
|
||||
tableMember = toMemberName(sqlTableName)
|
||||
tableNamespace = tableClass + '_'
|
||||
@ -386,10 +403,11 @@ for create in tableCreations:
|
||||
print(' };', file=header)
|
||||
print(' };', file=header)
|
||||
print(' };', file=header)
|
||||
if splitTables:
|
||||
endHeader(header, nsList)
|
||||
|
||||
for ns in nsList:
|
||||
print('} // namespace ' + ns, file=header)
|
||||
print('#endif', file=header)
|
||||
if not splitTables:
|
||||
endHeader(header, nsList)
|
||||
if (DataTypeError):
|
||||
print("Error: unsupported datatypes." )
|
||||
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}
|
||||
)
|
||||
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()
|
||||
|
||||
# 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})
|
||||
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)
|
||||
add_test(NAME 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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -38,7 +38,8 @@ int CustomQuery(int, char* [])
|
||||
auto db = MockDb{};
|
||||
|
||||
// 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()),
|
||||
"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))),
|
||||
" 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;
|
||||
}
|
||||
|
@ -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).set(bar.beta = "cheesecake", bar.gamma = true),
|
||||
"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;
|
||||
}
|
||||
|
@ -62,6 +62,11 @@ int Where(int, char* [])
|
||||
compare(__LINE__, where(bar.gamma), " WHERE tab_bar.gamma");
|
||||
compare(__LINE__, where(bar.gamma == false), " WHERE (tab_bar.gamma=" + getFalse() + ")");
|
||||
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;
|
||||
}
|
||||
|
@ -26,6 +26,12 @@ function(test_compile name)
|
||||
set(target sqlpp11_assert_${name})
|
||||
add_executable(${target} ${name}.cpp)
|
||||
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()
|
||||
|
||||
test_compile(aggregates)
|
||||
|
@ -26,6 +26,12 @@ function(test_compile name)
|
||||
set(target sqlpp11_${name})
|
||||
add_executable(${target} ${name}.cpp)
|
||||
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()
|
||||
|
||||
test_compile(result_row)
|
||||
|
@ -34,6 +34,7 @@ int BooleanExpression(int, char* [])
|
||||
const auto t = test::TabBar{};
|
||||
|
||||
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 = x and boolean_expression(db, t.gamma);
|
||||
|
||||
|
@ -57,6 +57,12 @@ endif()
|
||||
create_test_sourcelist(test_sources test_main.cpp ${test_names})
|
||||
add_executable(sqlpp11_tests ${test_sources})
|
||||
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)
|
||||
add_test(NAME sqlpp11.tests.${test}
|
||||
|
@ -29,6 +29,34 @@
|
||||
#include <sqlpp11/sqlpp11.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*[])
|
||||
{
|
||||
MockDb db = {};
|
||||
@ -61,6 +89,10 @@ int CustomQuery(int, char* [])
|
||||
db(custom_query(sqlpp::insert(), sqlpp::verbatim(" OR IGNORE"), into(t),
|
||||
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
|
||||
// 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();
|
||||
@ -69,6 +101,10 @@ int CustomQuery(int, char* [])
|
||||
auto i = db(c);
|
||||
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 :
|
||||
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.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();
|
||||
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"));
|
||||
static_assert(not sqlpp::is_selectable_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(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(not sqlpp::is_selectable_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));
|
||||
static_assert(not sqlpp::is_selectable_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(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(not sqlpp::is_selectable_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(not sqlpp::is_selectable_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(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(not sqlpp::is_selectable_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_selectable_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(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(not sqlpp::is_selectable_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).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();
|
||||
|
||||
@ -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 = sqlpp::default_value, t.beta = 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();
|
||||
i.insert_list.add(t.beta = "kirschauflauf");
|
||||
printer.reset();
|
||||
|
Loading…
Reference in New Issue
Block a user