[proof-of-concept] compile time query language
От: Evgeny.Panasyuk Россия  
Дата: 11.07.16 18:15
Оценка: 165 (13) +1 -1 :)

CTQL — Compile Time Query Language

В рамках одной из КСВ тем сделал proof-of-concept встроенного языка запросов времени компиляции, а точнее одной конкретной формы выражения (примеров EDSL и так предостаточно).
Все этапы, включая генерацию текста SQL запроса, вынесены в compile-time.

Пример использования

#include "ctql.hpp"

#include <iostream>

DEFINE_TABLE
(
    foo,
    (int, id)
    (int, code)
    (double, value)
    (int, number)
);

int main()
{
    using namespace CTQL;

    for(auto &&x : to_vector(
                       from(foo)
                       .where(foo.id > 42_i)
                       .select(foo.value, foo.id, foo.number)
                   ))
    {
        using namespace std;
        cout << "ROW: " << x.id << " " << x.value << " " << x.number << endl;
        // cout << x.code; // - compile error, because .code is not in projection
    }
}

Вывод

База-Данных-заглушка для контроля выводит информацию о производимых операциях. В строчке execute виден итоговый текст запроса:
execute SELECT foo.value, foo.id, foo.number FROM foo WHERE foo.id>42 
read_count 
get<double> 0 
get<int> 1 
get<int> 2 
move_to_next 
get<double> 0 
get<int> 1 
get<int> 2 
move_to_next 
get<double> 0 
get<int> 1 
get<int> 2 
move_to_next 
ROW: 100 1 200
ROW: 110 1.01 210
ROW: 120 1.02 220

Live Demo

Примеры автокомплита





Сравнение с ручным вариантом

В ручном варианте (функция handwritten ниже) всё жёстко закодировано оптимальным образом: готовый текст запроса, готовый результирующий тип строки результата, запрос колонок результата посредством целочисленных индексов:
#include "ctql.hpp"

#include <iostream>

DEFINE_TABLE
(
    foo,
    (int, id)
    (int, code)
    (double, value)
    (int, number)
);

NOINLINE auto handwritten()
{
    using namespace CTQL;

    struct Row
    {
        double value;
        int id;
        int number;
    } row;
    vector_noinline<Row> xs;

    dummy_db db;

    db.execute("SELECT foo.value, foo.id, foo.number FROM foo WHERE foo.id>42");

    auto count = db.read_count();
    xs.reserve(count);

    for(unsigned i=0; i!=count; ++i, db.move_to_next())
    {
        row.value = db.get<double>(0);
        row.id = db.get<int>(1);
        row.number = db.get<int>(2);

        xs.push_back(row);
    }

    return xs;
}

template<typename T>
void print(T &&xs)
{
    using namespace std;

    for(auto &x : xs)
        cout << "ROW: " << x.id << " " << x.value << " " << x.number << endl;
}

int main()
{
    using namespace CTQL;

    print( to_vector( from(foo).where(foo.id > 42_i).select(foo.value, foo.id, foo.number) ) );
    print_line();
    print( handwritten() );
}
  Вывод
execute SELECT foo.value, foo.id, foo.number FROM foo WHERE foo.id>42 
read_count 
get<double> 0 
get<int> 1 
get<int> 2 
move_to_next 
get<double> 0 
get<int> 1 
get<int> 2 
move_to_next 
get<double> 0 
get<int> 1 
get<int> 2 
move_to_next 
ROW: 100 1 200
ROW: 110 1.01 210
ROW: 120 1.02 220

execute SELECT foo.value, foo.id, foo.number FROM foo WHERE foo.id>42 
read_count 
get<double> 0 
get<int> 1 
get<int> 2 
move_to_next 
get<double> 0 
get<int> 1 
get<int> 2 
move_to_next 
get<double> 0 
get<int> 1 
get<int> 2 
move_to_next 
ROW: 100 1 200
ROW: 110 1.01 210
ROW: 120 1.02 220

Benchmark

Никакой benchmark не нужен, так как результирующий ассемблерный код в обоих вариантах идентичен, с точностью до идентификаторов — то есть истинный zero overhead
Собственно ради демонстрации нулевых расходов от EDSL запросов и затевался данный proof-of-concept.

Скрипт сравнения ассемблерного кода вариантов

g++ ctql.cpp -std=c++14 -O3 -Wall -pedantic -DNDEBUG -S -masm=intel &&
cat ctql.s | c++filt > ctql.filtered.s &&

sed -n '/.*auto CTQL::to_vector<.*):$/,/seh_endproc/p' ctql.filtered.s > to_vector.s &&
sed -n '/handwritten():$/,/seh_endproc/p' ctql.filtered.s > handwritten.s &&

diff -u handwritten.s to_vector.s > result.diff &&
cat result.diff
  ASM diff
--- handwritten.s   2016-07-11 21:12:30.407918000 +0300
+++ to_vector.s 2016-07-11 21:12:30.357917900 +0300
@@ -1,5 +1,5 @@
-handwritten():
-.LFB2021:
+auto CTQL::to_vector<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >(CTQL::query<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >):
+.LFB2067:
    push    r12
    .seh_pushreg    r12
    push    rbp
@@ -15,23 +15,23 @@
    .seh_endprologue
    lea rbx, 32[rsp]
    mov rdi, rcx
-   call    CTQL::vector_noinline<handwritten()::Row>::vector_noinline()
-   lea rdx, .LC9[rip]
+   call    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline()
+   lea rdx, CTQL::string_value<(char)83, (char)69, (char)76, (char)69, (char)67, (char)84, (char)32, (char)102, (char)111, (char)111, (char)46, (char)118, (char)97, (char)108, (char)117, (char)101, (char)44, (char)32, (char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)44, (char)32, (char)102, (char)111, (char)111, (char)46, (char)110, (char)117, (char)109, (char)98, (char)101, (char)114, (char)32, (char)70, (char)82, (char)79, (char)77, (char)32, (char)102, (char)111, (char)111, (char)32, (char)87, (char)72, (char)69, (char)82, (char)69, (char)32, (char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50>::value[rip]
    mov rcx, rbx
    mov DWORD PTR 32[rsp], 0
-.LEHB0:
+.LEHB2:
    call    CTQL::dummy_db::execute(char const*)
    call    CTQL::dummy_db::read_count() const [clone .isra.32]
    mov edx, eax
    mov rcx, rdi
    mov rbp, rdx
-   call    CTQL::vector_noinline<handwritten()::Row>::reserve(unsigned long) [clone .constprop.34]
+   call    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long)
    test    ebp, ebp
-   je  .L100
+   je  .L169
    lea r12, 48[rsp]
    xor esi, esi
    .p2align 4,,10
-.L103:
+.L172:
    mov rcx, rbx
    call    double CTQL::dummy_db::get<double>(unsigned int) const [clone .constprop.40]
    mov rcx, rbx
@@ -43,14 +43,14 @@
    mov rdx, r12
    mov rcx, rdi
    mov DWORD PTR 60[rsp], eax
-   call    CTQL::vector_noinline<handwritten()::Row>::push_back(handwritten()::Row const&) [clone .constprop.36]
+   call    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    mov rcx, rbx
    add esi, 1
    call    CTQL::dummy_db::move_to_next()
-.LEHE0:
+.LEHE2:
    cmp ebp, esi
-   jne .L103
-.L100:
+   jne .L172
+.L169:
    mov rax, rdi
    add rsp, 64
    pop rbx
@@ -59,32 +59,32 @@
    pop rbp
    pop r12
    ret
-.L106:
+.L175:
    mov rbx, rax
    mov rcx, rdi
-   call    CTQL::vector_noinline<handwritten()::Row>::~vector_noinline()
+   call    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline()
    mov rcx, rbx
-.LEHB1:
+.LEHB3:
    call    _Unwind_Resume
    nop
-.LEHE1:
-   .def    __gxx_personality_seh0; .scl    2;  .type   32; .endef
+.LEHE3:
    .seh_handler    __gxx_personality_seh0, @unwind, @except
    .seh_handlerdata
-.LLSDA2021:
+.LLSDA2067:
    .byte   0xff
    .byte   0xff
    .byte   0x1
-   .uleb128 .LLSDACSE2021-.LLSDACSB2021
-.LLSDACSB2021:
-   .uleb128 .LEHB0-.LFB2021
-   .uleb128 .LEHE0-.LEHB0
-   .uleb128 .L106-.LFB2021
+   .uleb128 .LLSDACSE2067-.LLSDACSB2067
+.LLSDACSB2067:
+   .uleb128 .LEHB2-.LFB2067
+   .uleb128 .LEHE2-.LEHB2
+   .uleb128 .L175-.LFB2067
    .uleb128 0
-   .uleb128 .LEHB1-.LFB2021
-   .uleb128 .LEHE1-.LEHB1
+   .uleb128 .LEHB3-.LFB2067
+   .uleb128 .LEHE3-.LEHB3
    .uleb128 0
    .uleb128 0
-.LLSDACSE2021:
-   .text
+.LLSDACSE2067:
+   .section    .text$_ZN4CTQL9to_vectorINS_10make_tableIN7foo_aux11name_stringEJNS2_9id_columnENS2_11code_columnENS2_12value_columnENS2_13number_columnEEEEKNS_8string_tIJLc102ELc111ELc111ELc46ELc105ELc100ELc62ELc52ELc50EEEEJNS_12table_columnIS2_dNS6_11field_valueEEENSC_IS2_iNS4_8field_idEEENSC_IS2_iNS7_12field_numberEEEEEEDaNS_5queryIT_T0_JDpT1_EEE,"x"
+   .linkonce discard
    .seh_endproc

Live Demo


Файлы

  ctql.hpp
// Copyright Evgeny Panasyuk 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// e-mail: E?????[dot]P???????[at]gmail.???

// C++ Compile-Time DB Query EDSL Proof-of-Concept

#ifndef CTQL_HPP
#define CTQL_HPP

/******************************************************************************/
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/pop_front.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/cat.hpp>

#include <initializer_list>
#include <type_traits>
#include <iostream>
#include <iterator>
#include <cassert>
#include <utility>
#include <vector>
#include <tuple>

namespace CTQL
{

/******************************************************************************/
#ifdef __GNUC__
    #define NOINLINE __attribute__((noinline))
#else
    #define NOINLINE
#endif

/******************************************************************************/
template<typename ...Ts>
void print_line(const Ts&... xs)
{
    using namespace std;
    (void)initializer_list<int>({(cout << xs << " ", 0)...});
    cout << endl;
}

/******************************************************************************/
class dummy_db
{
    unsigned current = 0;
public:
    NOINLINE void execute(const char *sql)
    {
        print_line("execute", sql);
        current = 0u;
    }
    NOINLINE unsigned read_count() const
    {
        using namespace std;
        print_line("read_count");
        return 3;
    }
    NOINLINE void move_to_next()
    {
        print_line("move_to_next");
        ++current;
    }
    template<typename T>
    NOINLINE T get(unsigned column) const;
};

template<>
NOINLINE int dummy_db::get<int>(unsigned column) const
{
    assert(column != 0 && column < 4);

    print_line("get<int>", column);
    return current*10 + column*100;
}

template<>
NOINLINE double dummy_db::get<double>(unsigned column) const
{
    assert(column == 0);

    print_line("get<double>", column);
    return 1.0 + current*0.01;
}

/******************************************************************************/
template<typename T>
struct vector_noinline
{
    std::vector<T> xs;

    NOINLINE vector_noinline() = default;
    NOINLINE ~vector_noinline() = default;
    NOINLINE vector_noinline(vector_noinline &&) = default;
    NOINLINE vector_noinline(const vector_noinline &) = default;

    NOINLINE void reserve(std::size_t n) { xs.reserve(n); }
    NOINLINE void push_back(const T &x) { xs.push_back(x); }
    auto begin() { return xs.begin(); }
    auto end() { return xs.end(); }
};

/******************************************************************************/
template<typename I, typename T>
constexpr I find(I first, T x)
{
    while(*first != x)
        ++first;
    return first;
}

constexpr std::size_t c_str_length(const char *x)
{
    return find(x, '\0') - x;
}

/******************************************************************************/
// compile-time string

template<char... cs>
struct string_value
{
    static constexpr const char value[sizeof...(cs)+1] = {cs..., '\0'};
};
template<char... cs>
constexpr const char string_value<cs...>::value[sizeof...(cs)+1];

template<char ...cs>
struct string_t
{
    using value_type = string_value<cs...>;
};

template<char ...cs>
constexpr string_t<cs...> string{};

template<typename String, std::size_t ...Is>
constexpr auto make_string_aux(String x, std::index_sequence<Is...>)
{
    return string<String::value()[Is]...>;
}

template<typename String>
constexpr auto make_string(String x)
{
    constexpr auto length = c_str_length(String::value());
    return make_string_aux(x, std::make_index_sequence<length>{});
}

/******************************************************************************/
constexpr auto concat()
{
    return string<>;
}

template<char ...cs>
constexpr auto concat(string_t<cs...> first)
{
    return first;
}

template<char ...cs1, char ...cs2, typename ...Rest>
constexpr auto concat
(
    string_t<cs1...> first,
    string_t<cs2...> second,
    Rest... rest
)
{
    return concat(string<cs1..., cs2...>, rest...);
}

/******************************************************************************/
template<typename T, typename U>
constexpr auto is_same(T, U)
{
    return std::false_type{};
}

template<typename T>
constexpr auto is_same(T, T)
{
    return std::true_type{};
}

template<typename TrueCase, typename FalseCase>
constexpr auto conditional(std::true_type, TrueCase true_case, FalseCase)
{
    return true_case;
}

template<typename TrueCase, typename FalseCase>
constexpr auto conditional(std::false_type, TrueCase, FalseCase false_case)
{
    return false_case;
}

using empty = string_t<>;

template<typename S, typename Rest>
constexpr auto skip_if_empty(S s, Rest rest)
{

    return conditional(is_same(s, empty{}), empty{}, rest);
}

/******************************************************************************/
template<char... digits>
constexpr auto operator"" _i() noexcept
{
    // static_assert
    return string<digits...>;
}

/******************************************************************************/
#define CTQL_STRUCT_WRAP_STRING(name, str)                              \
    struct name { static constexpr auto value() { return str; } }       \
/**/

#define CTQL_LAMBDA_WRAP_STRING(x)         \
    ([]                                    \
    {                                      \
        CTQL_STRUCT_WRAP_STRING(, x) str;  \
        return str;                        \
    })                                     \
/**/

template<typename Lambda>
constexpr auto make_string_from_lambda(Lambda x)
{
    return make_string(decltype(x()){});
}

#define CTQL_STRING(x)                                           \
    (CTQL::make_string_from_lambda(CTQL_LAMBDA_WRAP_STRING(x)))  \
/**/

/******************************************************************************/
constexpr auto space = string<' '>;
constexpr auto comma = string<','>;
constexpr auto dot = string<'.'>;

/******************************************************************************/
template<typename Field>
constexpr auto name_string(Field)
{
    return make_string(typename Field::name_string{});
}

/******************************************************************************/
#define FIELD(name)                                                     \
    struct BOOST_PP_CAT(field_, name)                                   \
    {                                                                   \
        CTQL_STRUCT_WRAP_STRING(name_string, BOOST_PP_STRINGIZE(name)); \
        template<typename T>                                            \
        struct field                                                    \
        {                                                               \
            T name;                                                     \
        };                                                              \
        template<typename T>                                            \
        static auto &access(T &x)                                       \
        {                                                               \
            return x.name;                                              \
        }                                                               \
    }                                                                   \
/**/

/******************************************************************************/
template<typename Column>
constexpr auto full_column_name(Column column)
{
    return concat
    (
        name_string(typename Column::table{}),
        dot,
        name_string(typename Column::field{})
    );    
}

template<typename Table, typename T, typename Field>
struct table_column
{
    using table = Table;
    using column_type = T;
    using field = Field;

    template<char ...cs>
    constexpr auto operator>(string_t<cs...> x) const
    {
        return concat(full_column_name(table_column{}), string<'>'>, x);
    }
};

template<typename Name, typename ...Columns>
struct make_table
    : Columns::type::field::template field<typename Columns::type>...
{
    using name_string = Name;
};

template<typename ...Columns>
struct make_row
    : Columns::field::template field<typename Columns::column_type>...
{};

/******************************************************************************/
// map db result onto row

template<typename Ts, typename Row, typename Db, std::size_t ...Is>
void map_result_aux(Row &row, Db &db, std::index_sequence<Is...>)
{
    (void)std::initializer_list<int>(
    {
        (
            (void)
            (
                std::tuple_element_t<Is, Ts>::field::access(row) =
                    db.template get
                    <
                        typename std::tuple_element_t<Is, Ts>::column_type
                    >(Is)
            ),
            0
        )...
    });
}

template<typename ...Ts, typename Row, typename Db>
void map_result(Row &row, Db &db)
{
    map_result_aux<std::tuple<Ts...>>
        (row, db, std::make_index_sequence<sizeof...(Ts)>());
}

/******************************************************************************/
// query EDSL

template<typename Table, typename Condition, typename ...Columns>
struct query
{
    using source = Table;
    using condition = Condition;
    using projection = std::tuple<Columns...>;

    template<typename ...RightColumns>
    auto select(RightColumns...) const
    {
        return query<Table, Condition, Columns..., RightColumns...>{};
    }

    template<typename RightCondition>
    auto where(RightCondition right_condition) const
    {
        constexpr auto new_condition = concat
        (
            skip_if_empty
            (
                Condition{},
                concat(Condition{}, CTQL_STRING(" AND "))
            ),
            right_condition
        );

        return query<Table, decltype(new_condition), Columns...>{};
    }
};

template<typename Table>
auto from(Table)
{
    return query<Table, empty>{};
}

/******************************************************************************/
// SQL generation

template<typename Source>
constexpr auto source_string(Source source)
{
    return name_string(source);
}

template<typename FirstColumn, typename ...Rest>
constexpr auto concat_columns(FirstColumn first_column, Rest... rest)
{
    return concat
    (
        full_column_name(first_column),
        concat(comma, space, full_column_name(rest))...
    );
}

template<typename Source, typename Condition, typename ...Columns>
constexpr auto make_sql
(
    Source source, Condition condition,
    Columns... columns
)
{
    return concat
    (
        CTQL_STRING("SELECT "), concat_columns(columns...),
        CTQL_STRING(" FROM "), source_string(source),
        skip_if_empty(condition, concat(CTQL_STRING(" WHERE "), condition))
    );
}

/******************************************************************************/
// Inner Query
template<typename Source, typename ...Ts>
constexpr auto source_string(query<Source, Ts...>)
{
    return concat(string<'('>, make_sql(Source{}, Ts{}...), string<')'>);
}

#ifdef CTQL_TRANSFORM_FROM_SUBQUERY
// transform
template
<
    typename SubSource, typename SubCondition, typename ...SubColumns,
    typename Condition, typename ...Columns
>
constexpr auto make_sql
(
    query<SubSource, SubCondition, SubColumns...>,
    Condition condition,
    Columns... columns
)
{
    return make_sql
    (
        SubSource{},
        concat(condition, CTQL_STRING(" AND "), SubCondition{}),
        columns...
    );
}
#endif

/******************************************************************************/
template<typename Table, typename Condition, typename ...Columns>
NOINLINE auto to_vector(query<Table, Condition, Columns...>)
{
    using sql_text = decltype(make_sql(Table{}, Condition{}, Columns{}...));

    using Row = make_row<Columns...>;
    Row row;

    vector_noinline<Row> xs;

    dummy_db db;
    db.execute(sql_text::value_type::value);
    auto count = db.read_count();
    xs.reserve(count);

    for(unsigned i=0; i!=count; ++i, db.move_to_next())
    {
        map_result<Columns...>(row, db);
        xs.push_back(row);
    }

    return xs;
}

/******************************************************************************/
// table definition macro
// refer http://www.boost.org/doc/libs/1_56_0/boost/fusion/adapted/struct/define_struct.hpp
// rerquired for sequence of tuples syntax ((a,b)(c,d)...)

#define PAIR_TYPE_0(X, Y) ((X, Y)) PAIR_TYPE_1
#define PAIR_TYPE_1(X, Y) ((X, Y)) PAIR_TYPE_0
#define PAIR_TYPE_0_END
#define PAIR_TYPE_1_END

#define PAIR_FIRST(elem) BOOST_PP_TUPLE_ELEM(2, 0, elem)
#define PAIR_SECOND(elem) BOOST_PP_TUPLE_ELEM(2, 1, elem)


#define DECLARE_COLUMN(r, data, i, elem)            \
    struct BOOST_PP_CAT(PAIR_SECOND(elem), _column) \
    {                                               \
        FIELD(PAIR_SECOND(elem));                   \
        using type = CTQL::table_column             \
        <                                           \
            table_type,                             \
            PAIR_FIRST(elem),                       \
            BOOST_PP_CAT(field_, PAIR_SECOND(elem)) \
        >;                                          \
    };                                              \
/**/

#define COLUMN_NAME(r, data, i, elem) , BOOST_PP_CAT(PAIR_SECOND(elem), _column)

#define FOR_EACH_DECL(action, seq) \
    BOOST_PP_SEQ_FOR_EACH_I(action, _, BOOST_PP_SEQ_POP_FRONT(BOOST_PP_CAT(PAIR_TYPE_0(0,0)seq,_END))) \
/**/

#define DEFINE_TABLE(name, seq)                                                     \
    struct name ## _aux                                                             \
    {                                                                               \
        using table_type = name ## _aux;                                            \
        FOR_EACH_DECL(DECLARE_COLUMN, seq)                                          \
        CTQL_STRUCT_WRAP_STRING(name_string, #name);                                \
        using type = CTQL::make_table<name_string FOR_EACH_DECL(COLUMN_NAME, seq)>; \
    };                                                                              \
    name ## _aux :: type name                                                       \
/**/


} // namespace end

#endif
  ctql.cpp
#include "ctql.hpp"

#include <iostream>

DEFINE_TABLE
(
    foo,
    (int, id)
    (int, code)
    (double, value)
    (int, number)
);

NOINLINE auto handwritten()
{
    using namespace CTQL;

    struct Row
    {
        double value;
        int id;
        int number;
    } row;
    vector_noinline<Row> xs;

    dummy_db db;

    db.execute("SELECT foo.value, foo.id, foo.number FROM foo WHERE foo.id>42");

    auto count = db.read_count();
    xs.reserve(count);

    for(unsigned i=0; i!=count; ++i, db.move_to_next())
    {
        row.value = db.get<double>(0);
        row.id = db.get<int>(1);
        row.number = db.get<int>(2);

        xs.push_back(row);
    }

    return xs;
}

template<typename T>
void print(T &&xs)
{
    using namespace std;

    for(auto &x : xs)
        cout << "ROW: " << x.id << " " << x.value << " " << x.number << endl;
}

int main()
{
    using namespace CTQL;

    print( to_vector( from(foo).where(foo.id > 42_i).select(foo.value, foo.id, foo.number) ) );
    print_line();
    print( handwritten() );
}
  to_vector.s
auto CTQL::to_vector<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >(CTQL::query<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >):
.LFB2067:
    push    r12
    .seh_pushreg    r12
    push    rbp
    .seh_pushreg    rbp
    push    rdi
    .seh_pushreg    rdi
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 64
    .seh_stackalloc 64
    .seh_endprologue
    lea rbx, 32[rsp]
    mov rdi, rcx
    call    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline()
    lea rdx, CTQL::string_value<(char)83, (char)69, (char)76, (char)69, (char)67, (char)84, (char)32, (char)102, (char)111, (char)111, (char)46, (char)118, (char)97, (char)108, (char)117, (char)101, (char)44, (char)32, (char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)44, (char)32, (char)102, (char)111, (char)111, (char)46, (char)110, (char)117, (char)109, (char)98, (char)101, (char)114, (char)32, (char)70, (char)82, (char)79, (char)77, (char)32, (char)102, (char)111, (char)111, (char)32, (char)87, (char)72, (char)69, (char)82, (char)69, (char)32, (char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50>::value[rip]
    mov rcx, rbx
    mov DWORD PTR 32[rsp], 0
.LEHB2:
    call    CTQL::dummy_db::execute(char const*)
    call    CTQL::dummy_db::read_count() const [clone .isra.32]
    mov edx, eax
    mov rcx, rdi
    mov rbp, rdx
    call    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long)
    test    ebp, ebp
    je  .L169
    lea r12, 48[rsp]
    xor esi, esi
    .p2align 4,,10
.L172:
    mov rcx, rbx
    call    double CTQL::dummy_db::get<double>(unsigned int) const [clone .constprop.40]
    mov rcx, rbx
    movsd   QWORD PTR 48[rsp], xmm0
    call    int CTQL::dummy_db::get<int>(unsigned int) const [clone .constprop.41]
    mov rcx, rbx
    mov DWORD PTR 56[rsp], eax
    call    int CTQL::dummy_db::get<int>(unsigned int) const [clone .constprop.42]
    mov rdx, r12
    mov rcx, rdi
    mov DWORD PTR 60[rsp], eax
    call    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    mov rcx, rbx
    add esi, 1
    call    CTQL::dummy_db::move_to_next()
.LEHE2:
    cmp ebp, esi
    jne .L172
.L169:
    mov rax, rdi
    add rsp, 64
    pop rbx
    pop rsi
    pop rdi
    pop rbp
    pop r12
    ret
.L175:
    mov rbx, rax
    mov rcx, rdi
    call    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline()
    mov rcx, rbx
.LEHB3:
    call    _Unwind_Resume
    nop
.LEHE3:
    .seh_handler    __gxx_personality_seh0, @unwind, @except
    .seh_handlerdata
.LLSDA2067:
    .byte   0xff
    .byte   0xff
    .byte   0x1
    .uleb128 .LLSDACSE2067-.LLSDACSB2067
.LLSDACSB2067:
    .uleb128 .LEHB2-.LFB2067
    .uleb128 .LEHE2-.LEHB2
    .uleb128 .L175-.LFB2067
    .uleb128 0
    .uleb128 .LEHB3-.LFB2067
    .uleb128 .LEHE3-.LEHB3
    .uleb128 0
    .uleb128 0
.LLSDACSE2067:
    .section    .text$_ZN4CTQL9to_vectorINS_10make_tableIN7foo_aux11name_stringEJNS2_9id_columnENS2_11code_columnENS2_12value_columnENS2_13number_columnEEEEKNS_8string_tIJLc102ELc111ELc111ELc46ELc105ELc100ELc62ELc52ELc50EEEEJNS_12table_columnIS2_dNS6_11field_valueEEENSC_IS2_iNS4_8field_idEEENSC_IS2_iNS7_12field_numberEEEEEEDaNS_5queryIT_T0_JDpT1_EEE,"x"
    .linkonce discard
    .seh_endproc
  handwritten.s
handwritten():
.LFB2021:
    push    r12
    .seh_pushreg    r12
    push    rbp
    .seh_pushreg    rbp
    push    rdi
    .seh_pushreg    rdi
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 64
    .seh_stackalloc 64
    .seh_endprologue
    lea rbx, 32[rsp]
    mov rdi, rcx
    call    CTQL::vector_noinline<handwritten()::Row>::vector_noinline()
    lea rdx, .LC9[rip]
    mov rcx, rbx
    mov DWORD PTR 32[rsp], 0
.LEHB0:
    call    CTQL::dummy_db::execute(char const*)
    call    CTQL::dummy_db::read_count() const [clone .isra.32]
    mov edx, eax
    mov rcx, rdi
    mov rbp, rdx
    call    CTQL::vector_noinline<handwritten()::Row>::reserve(unsigned long) [clone .constprop.34]
    test    ebp, ebp
    je  .L100
    lea r12, 48[rsp]
    xor esi, esi
    .p2align 4,,10
.L103:
    mov rcx, rbx
    call    double CTQL::dummy_db::get<double>(unsigned int) const [clone .constprop.40]
    mov rcx, rbx
    movsd   QWORD PTR 48[rsp], xmm0
    call    int CTQL::dummy_db::get<int>(unsigned int) const [clone .constprop.41]
    mov rcx, rbx
    mov DWORD PTR 56[rsp], eax
    call    int CTQL::dummy_db::get<int>(unsigned int) const [clone .constprop.42]
    mov rdx, r12
    mov rcx, rdi
    mov DWORD PTR 60[rsp], eax
    call    CTQL::vector_noinline<handwritten()::Row>::push_back(handwritten()::Row const&) [clone .constprop.36]
    mov rcx, rbx
    add esi, 1
    call    CTQL::dummy_db::move_to_next()
.LEHE0:
    cmp ebp, esi
    jne .L103
.L100:
    mov rax, rdi
    add rsp, 64
    pop rbx
    pop rsi
    pop rdi
    pop rbp
    pop r12
    ret
.L106:
    mov rbx, rax
    mov rcx, rdi
    call    CTQL::vector_noinline<handwritten()::Row>::~vector_noinline()
    mov rcx, rbx
.LEHB1:
    call    _Unwind_Resume
    nop
.LEHE1:
    .def    __gxx_personality_seh0; .scl    2;  .type   32; .endef
    .seh_handler    __gxx_personality_seh0, @unwind, @except
    .seh_handlerdata
.LLSDA2021:
    .byte   0xff
    .byte   0xff
    .byte   0x1
    .uleb128 .LLSDACSE2021-.LLSDACSB2021
.LLSDACSB2021:
    .uleb128 .LEHB0-.LFB2021
    .uleb128 .LEHE0-.LEHB0
    .uleb128 .L106-.LFB2021
    .uleb128 0
    .uleb128 .LEHB1-.LFB2021
    .uleb128 .LEHE1-.LEHB1
    .uleb128 0
    .uleb128 0
.LLSDACSE2021:
    .text
    .seh_endproc
  ctql.filtered.s
    .file   "ctql.cpp"
    .intel_syntax noprefix
    .section    .text$_ZNKSt5ctypeIcE8do_widenEc,"x"
    .linkonce discard
    .align 2
    .p2align 4,,15
    .globl  std::ctype<char>::do_widen(char) const
    .def    std::ctype<char>::do_widen(char) const; .scl    2;  .type   32; .endef
    .seh_proc   std::ctype<char>::do_widen(char) const
std::ctype<char>::do_widen(char) const:
.LFB1178:
    .seh_endprologue
    mov eax, edx
    ret
    .seh_endproc
    .text
    .align 2
    .p2align 4,,15
    .def    CTQL::vector_noinline<handwritten()::Row>::vector_noinline();   .scl    3;  .type   32; .endef
    .seh_proc   CTQL::vector_noinline<handwritten()::Row>::vector_noinline()
CTQL::vector_noinline<handwritten()::Row>::vector_noinline():
.LFB2023:
    .seh_endprologue
    mov QWORD PTR [rcx], 0
    mov QWORD PTR 8[rcx], 0
    mov QWORD PTR 16[rcx], 0
    ret
    .seh_endproc
    .def    CTQL::vector_noinline<handwritten()::Row>::vector_noinline();   .scl    3;  .type   32; .endef
    .set    CTQL::vector_noinline<handwritten()::Row>::vector_noinline(),CTQL::vector_noinline<handwritten()::Row>::vector_noinline()
    .align 2
    .p2align 4,,15
    .def    CTQL::vector_noinline<handwritten()::Row>::~vector_noinline();  .scl    3;  .type   32; .endef
    .seh_proc   CTQL::vector_noinline<handwritten()::Row>::~vector_noinline()
CTQL::vector_noinline<handwritten()::Row>::~vector_noinline():
.LFB2026:
    .seh_endprologue
    mov rcx, QWORD PTR [rcx]
    test    rcx, rcx
    je  .L3
    jmp operator delete(void*)
.L3:
    ret
    .seh_endproc
    .def    CTQL::vector_noinline<handwritten()::Row>::~vector_noinline();  .scl    3;  .type   32; .endef
    .set    CTQL::vector_noinline<handwritten()::Row>::~vector_noinline(),CTQL::vector_noinline<handwritten()::Row>::~vector_noinline()
    .align 2
    .p2align 4,,15
    .def    CTQL::vector_noinline<handwritten()::Row>::push_back(handwritten()::Row const&) [clone .constprop.36];  .scl    3;  .type   32; .endef
    .seh_proc   CTQL::vector_noinline<handwritten()::Row>::push_back(handwritten()::Row const&) [clone .constprop.36]
CTQL::vector_noinline<handwritten()::Row>::push_back(handwritten()::Row const&) [clone .constprop.36]:
.LFB2708:
    push    r12
    .seh_pushreg    r12
    push    rbp
    .seh_pushreg    rbp
    push    rdi
    .seh_pushreg    rdi
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 48
    .seh_stackalloc 48
    .seh_endprologue
    mov r8, QWORD PTR 8[rcx]
    cmp r8, QWORD PTR 16[rcx]
    mov rbx, rcx
    je  .L7
    test    r8, r8
    je  .L8
    mov rax, QWORD PTR [rdx]
    mov rdx, QWORD PTR 8[rdx]
    mov QWORD PTR [r8], rax
    mov QWORD PTR 8[r8], rdx
.L8:
    add r8, 16
    mov QWORD PTR 8[rbx], r8
.L6:
    add rsp, 48
    pop rbx
    pop rsi
    pop rdi
    pop rbp
    pop r12
    ret
    .p2align 4,,10
.L7:
    mov rax, r8
    sub rax, QWORD PTR [rcx]
    sar rax, 4
    test    rax, rax
    je  .L17
    lea rcx, [rax+rax]
    cmp rax, rcx
    jbe .L30
.L18:
    mov rbp, -16
.L10:
    mov rcx, rbp
    mov QWORD PTR 40[rsp], rdx
    call    operator new(unsigned long)
    mov r8, QWORD PTR 8[rbx]
    mov rdx, QWORD PTR 40[rsp]
    mov rsi, rax
.L16:
    mov r12, QWORD PTR [rbx]
    mov rdi, rsi
    sub r8, r12
    mov rax, r8
    sar rax, 4
    add rdi, r8
    je  .L12
    mov r9, QWORD PTR [rdx]
    mov r10, QWORD PTR 8[rdx]
    mov QWORD PTR [rdi], r9
    mov QWORD PTR 8[rdi], r10
.L12:
    test    rax, rax
    jne .L31
    add rdi, 16
    test    r12, r12
    je  .L15
.L14:
    mov rcx, r12
    call    operator delete(void*)
.L15:
    mov QWORD PTR [rbx], rsi
    add rsi, rbp
    mov QWORD PTR 8[rbx], rdi
    mov QWORD PTR 16[rbx], rsi
    jmp .L6
    .p2align 4,,10
.L17:
    mov ebp, 16
    jmp .L10
    .p2align 4,,10
.L31:
    mov rdx, r12
    mov rcx, rsi
    add rdi, 16
    call    memmove
    jmp .L14
.L30:
    movabs  r9, 1152921504606846975
    cmp rcx, r9
    ja  .L18
    xor ebp, ebp
    xor esi, esi
    test    rcx, rcx
    je  .L16
    sal rax, 5
    mov rbp, rax
    jmp .L10
    .seh_endproc
    .section .rdata,"dr"
.LC0:
    .ascii "vector::reserve\0"
    .text
    .align 2
    .p2align 4,,15
    .def    CTQL::vector_noinline<handwritten()::Row>::reserve(unsigned long) [clone .constprop.34];    .scl    3;  .type   32; .endef
    .seh_proc   CTQL::vector_noinline<handwritten()::Row>::reserve(unsigned long) [clone .constprop.34]
CTQL::vector_noinline<handwritten()::Row>::reserve(unsigned long) [clone .constprop.34]:
.LFB2710:
    push    r13
    .seh_pushreg    r13
    push    r12
    .seh_pushreg    r12
    push    rbp
    .seh_pushreg    rbp
    push    rdi
    .seh_pushreg    rdi
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 40
    .seh_stackalloc 40
    .seh_endprologue
    movabs  rax, 1152921504606846975
    cmp rdx, rax
    mov rsi, rcx
    ja  .L43
    mov rbp, QWORD PTR [rcx]
    mov rax, QWORD PTR 16[rcx]
    sub rax, rbp
    sar rax, 4
    cmp rdx, rax
    ja  .L44
    add rsp, 40
    pop rbx
    pop rsi
    pop rdi
    pop rbp
    pop r12
    pop r13
    ret
    .p2align 4,,10
.L44:
    mov rdi, QWORD PTR 8[rcx]
    sub rdi, rbp
    test    rdx, rdx
    je  .L39
    mov rbx, rdx
    sal rbx, 4
    mov rcx, rbx
    call    operator new(unsigned long)
    mov r13, QWORD PTR [rsi]
    mov r12, rax
.L35:
    mov rax, rdi
    sar rax, 4
    test    rax, rax
    je  .L37
    mov r8, rdi
    mov rdx, rbp
    mov rcx, r12
    call    memmove
.L37:
    test    r13, r13
    je  .L38
    mov rcx, r13
    call    operator delete(void*)
.L38:
    lea rdx, [r12+rbx]
    add rdi, r12
    mov QWORD PTR [rsi], r12
    mov QWORD PTR 8[rsi], rdi
    mov QWORD PTR 16[rsi], rdx
    add rsp, 40
    pop rbx
    pop rsi
    pop rdi
    pop rbp
    pop r12
    pop r13
    ret
    .p2align 4,,10
.L39:
    mov r13, rbp
    xor ebx, ebx
    xor r12d, r12d
    jmp .L35
.L43:
    lea rcx, .LC0[rip]
    call    std::__throw_length_error(char const*)
    nop
    .seh_endproc
    .section .rdata,"dr"
.LC1:
    .ascii "read_count\0"
.LC2:
    .ascii " \0"
    .text
    .align 2
    .p2align 4,,15
    .def    CTQL::dummy_db::read_count() const [clone .isra.32];    .scl    3;  .type   32; .endef
    .seh_proc   CTQL::dummy_db::read_count() const [clone .isra.32]
CTQL::dummy_db::read_count() const [clone .isra.32]:
.LFB2696:
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 32
    .seh_stackalloc 32
    .seh_endprologue
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    lea rdx, .LC1[rip]
    mov r8d, 10
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    lea rdx, .LC2[rip]
    mov r8d, 1
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rax, QWORD PTR .refptr._ZSt4cout[rip]
    mov rdx, QWORD PTR [rax]
    mov rdx, QWORD PTR -24[rdx]
    mov rbx, QWORD PTR 240[rdx+rax]
    test    rbx, rbx
    je  .L50
    cmp BYTE PTR 56[rbx], 0
    je  .L47
    movsx   edx, BYTE PTR 67[rbx]
.L48:
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    call    std::basic_ostream<char, std::char_traits<char> >::put(char)
    mov rcx, rax
    call    std::basic_ostream<char, std::char_traits<char> >::flush()
    mov eax, 3
    add rsp, 32
    pop rbx
    ret
    .p2align 4,,10
.L47:
    mov rcx, rbx
    call    std::ctype<char>::_M_widen_init() const
    mov rax, QWORD PTR [rbx]
    lea rcx, std::ctype<char>::do_widen(char) const[rip]
    mov edx, 10
    mov rax, QWORD PTR 48[rax]
    cmp rax, rcx
    je  .L48
    mov rcx, rbx
    call    rax
    movsx   edx, al
    jmp .L48
.L50:
    call    std::__throw_bad_cast()
    nop
    .seh_endproc
    .section .rdata,"dr"
.LC3:
    .ascii "get<double>\0"
    .text
    .align 2
    .p2align 4,,15
    .def    double CTQL::dummy_db::get<double>(unsigned int) const [clone .constprop.40];   .scl    3;  .type   32; .endef
    .seh_proc   double CTQL::dummy_db::get<double>(unsigned int) const [clone .constprop.40]
double CTQL::dummy_db::get<double>(unsigned int) const [clone .constprop.40]:
.LFB2704:
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 40
    .seh_stackalloc 40
    .seh_endprologue
    lea rdx, .LC3[rip]
    mov r8d, 11
    mov rsi, rcx
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    lea rdx, .LC2[rip]
    mov r8d, 1
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    xor edx, edx
    call    std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<unsigned long>(unsigned long)
    lea rdx, .LC2[rip]
    mov r8d, 1
    mov rcx, rax
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rax, QWORD PTR .refptr._ZSt4cout[rip]
    mov rdx, QWORD PTR [rax]
    mov rdx, QWORD PTR -24[rdx]
    mov rbx, QWORD PTR 240[rdx+rax]
    test    rbx, rbx
    je  .L58
    cmp BYTE PTR 56[rbx], 0
    je  .L53
    movsx   edx, BYTE PTR 67[rbx]
.L54:
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    call    std::basic_ostream<char, std::char_traits<char> >::put(char)
    mov rcx, rax
    call    std::basic_ostream<char, std::char_traits<char> >::flush()
    mov eax, DWORD PTR [rsi]
    pxor    xmm0, xmm0
    cvtsi2sdq   xmm0, rax
    mulsd   xmm0, QWORD PTR .LC4[rip]
    addsd   xmm0, QWORD PTR .LC5[rip]
    add rsp, 40
    pop rbx
    pop rsi
    ret
    .p2align 4,,10
.L53:
    mov rcx, rbx
    call    std::ctype<char>::_M_widen_init() const
    mov rax, QWORD PTR [rbx]
    lea rcx, std::ctype<char>::do_widen(char) const[rip]
    mov edx, 10
    mov rax, QWORD PTR 48[rax]
    cmp rax, rcx
    je  .L54
    mov rcx, rbx
    call    rax
    movsx   edx, al
    jmp .L54
.L58:
    call    std::__throw_bad_cast()
    nop
    .seh_endproc
    .section .rdata,"dr"
.LC6:
    .ascii "get<int>\0"
    .text
    .align 2
    .p2align 4,,15
    .def    int CTQL::dummy_db::get<int>(unsigned int) const [clone .constprop.42]; .scl    3;  .type   32; .endef
    .seh_proc   int CTQL::dummy_db::get<int>(unsigned int) const [clone .constprop.42]
int CTQL::dummy_db::get<int>(unsigned int) const [clone .constprop.42]:
.LFB2702:
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 40
    .seh_stackalloc 40
    .seh_endprologue
    lea rdx, .LC6[rip]
    mov r8d, 8
    mov rsi, rcx
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    lea rdx, .LC2[rip]
    mov r8d, 1
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    mov edx, 2
    call    std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<unsigned long>(unsigned long)
    lea rdx, .LC2[rip]
    mov r8d, 1
    mov rcx, rax
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rax, QWORD PTR .refptr._ZSt4cout[rip]
    mov rdx, QWORD PTR [rax]
    mov rdx, QWORD PTR -24[rdx]
    mov rbx, QWORD PTR 240[rdx+rax]
    test    rbx, rbx
    je  .L64
    cmp BYTE PTR 56[rbx], 0
    je  .L61
    movsx   edx, BYTE PTR 67[rbx]
.L62:
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    call    std::basic_ostream<char, std::char_traits<char> >::put(char)
    mov rcx, rax
    call    std::basic_ostream<char, std::char_traits<char> >::flush()
    mov eax, DWORD PTR [rsi]
    lea eax, [rax+rax*4]
    lea eax, 200[rax+rax]
    add rsp, 40
    pop rbx
    pop rsi
    ret
    .p2align 4,,10
.L61:
    mov rcx, rbx
    call    std::ctype<char>::_M_widen_init() const
    mov rax, QWORD PTR [rbx]
    lea rcx, std::ctype<char>::do_widen(char) const[rip]
    mov edx, 10
    mov rax, QWORD PTR 48[rax]
    cmp rax, rcx
    je  .L62
    mov rcx, rbx
    call    rax
    movsx   edx, al
    jmp .L62
.L64:
    call    std::__throw_bad_cast()
    nop
    .seh_endproc
    .align 2
    .p2align 4,,15
    .def    int CTQL::dummy_db::get<int>(unsigned int) const [clone .constprop.41]; .scl    3;  .type   32; .endef
    .seh_proc   int CTQL::dummy_db::get<int>(unsigned int) const [clone .constprop.41]
int CTQL::dummy_db::get<int>(unsigned int) const [clone .constprop.41]:
.LFB2703:
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 40
    .seh_stackalloc 40
    .seh_endprologue
    lea rdx, .LC6[rip]
    mov r8d, 8
    mov rsi, rcx
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    lea rdx, .LC2[rip]
    mov r8d, 1
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    mov edx, 1
    call    std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<unsigned long>(unsigned long)
    lea rdx, .LC2[rip]
    mov r8d, 1
    mov rcx, rax
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rax, QWORD PTR .refptr._ZSt4cout[rip]
    mov rdx, QWORD PTR [rax]
    mov rdx, QWORD PTR -24[rdx]
    mov rbx, QWORD PTR 240[rdx+rax]
    test    rbx, rbx
    je  .L70
    cmp BYTE PTR 56[rbx], 0
    je  .L67
    movsx   edx, BYTE PTR 67[rbx]
.L68:
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    call    std::basic_ostream<char, std::char_traits<char> >::put(char)
    mov rcx, rax
    call    std::basic_ostream<char, std::char_traits<char> >::flush()
    mov eax, DWORD PTR [rsi]
    lea eax, [rax+rax*4]
    lea eax, 100[rax+rax]
    add rsp, 40
    pop rbx
    pop rsi
    ret
    .p2align 4,,10
.L67:
    mov rcx, rbx
    call    std::ctype<char>::_M_widen_init() const
    mov rax, QWORD PTR [rbx]
    lea rcx, std::ctype<char>::do_widen(char) const[rip]
    mov edx, 10
    mov rax, QWORD PTR 48[rax]
    cmp rax, rcx
    je  .L68
    mov rcx, rbx
    call    rax
    movsx   edx, al
    jmp .L68
.L70:
    call    std::__throw_bad_cast()
    nop
    .seh_endproc
    .section .rdata,"dr"
.LC7:
    .ascii "execute\0"
    .section    .text$_ZN4CTQL8dummy_db7executeEPKc,"x"
    .linkonce discard
    .align 2
    .p2align 4,,15
    .globl  CTQL::dummy_db::execute(char const*)
    .def    CTQL::dummy_db::execute(char const*);   .scl    2;  .type   32; .endef
    .seh_proc   CTQL::dummy_db::execute(char const*)
CTQL::dummy_db::execute(char const*):
.LFB1967:
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 40
    .seh_stackalloc 40
    .seh_endprologue
    mov r8d, 7
    mov rsi, rcx
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    mov rbx, rdx
    lea rdx, .LC7[rip]
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    lea rdx, .LC2[rip]
    mov r8d, 1
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    test    rbx, rbx
    je  .L78
    mov rcx, rbx
    call    strlen
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    mov rdx, rbx
    mov r8, rax
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rbx, QWORD PTR .refptr._ZSt4cout[rip]
    mov rcx, rbx
.L73:
    lea rdx, .LC2[rip]
    mov r8d, 1
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rax, QWORD PTR [rbx]
    mov rax, QWORD PTR -24[rax]
    mov rbx, QWORD PTR 240[rbx+rax]
    test    rbx, rbx
    je  .L79
    cmp BYTE PTR 56[rbx], 0
    je  .L75
    movsx   edx, BYTE PTR 67[rbx]
.L76:
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    call    std::basic_ostream<char, std::char_traits<char> >::put(char)
    mov rcx, rax
    call    std::basic_ostream<char, std::char_traits<char> >::flush()
    mov DWORD PTR [rsi], 0
    add rsp, 40
    pop rbx
    pop rsi
    ret
    .p2align 4,,10
.L75:
    mov rcx, rbx
    call    std::ctype<char>::_M_widen_init() const
    mov rax, QWORD PTR [rbx]
    lea rcx, std::ctype<char>::do_widen(char) const[rip]
    mov edx, 10
    mov rax, QWORD PTR 48[rax]
    cmp rax, rcx
    je  .L76
    mov rcx, rbx
    call    rax
    movsx   edx, al
    jmp .L76
    .p2align 4,,10
.L78:
    mov rbx, QWORD PTR .refptr._ZSt4cout[rip]
    mov rax, QWORD PTR [rbx]
    mov rcx, rbx
    add rcx, QWORD PTR -24[rax]
    mov edx, DWORD PTR 32[rcx]
    or  edx, 1
    call    std::basic_ios<char, std::char_traits<char> >::clear(std::_Ios_Iostate)
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    jmp .L73
.L79:
    call    std::__throw_bad_cast()
    nop
    .seh_endproc
    .section .rdata,"dr"
.LC8:
    .ascii "move_to_next\0"
    .section    .text$_ZN4CTQL8dummy_db12move_to_nextEv,"x"
    .linkonce discard
    .align 2
    .p2align 4,,15
    .globl  CTQL::dummy_db::move_to_next()
    .def    CTQL::dummy_db::move_to_next(); .scl    2;  .type   32; .endef
    .seh_proc   CTQL::dummy_db::move_to_next()
CTQL::dummy_db::move_to_next():
.LFB1969:
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 40
    .seh_stackalloc 40
    .seh_endprologue
    lea rdx, .LC8[rip]
    mov r8d, 12
    mov rsi, rcx
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    lea rdx, .LC2[rip]
    mov r8d, 1
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rax, QWORD PTR .refptr._ZSt4cout[rip]
    mov rdx, QWORD PTR [rax]
    mov rdx, QWORD PTR -24[rdx]
    mov rbx, QWORD PTR 240[rdx+rax]
    test    rbx, rbx
    je  .L85
    cmp BYTE PTR 56[rbx], 0
    je  .L82
    movsx   edx, BYTE PTR 67[rbx]
.L83:
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    call    std::basic_ostream<char, std::char_traits<char> >::put(char)
    mov rcx, rax
    call    std::basic_ostream<char, std::char_traits<char> >::flush()
    add DWORD PTR [rsi], 1
    add rsp, 40
    pop rbx
    pop rsi
    ret
    .p2align 4,,10
.L82:
    mov rcx, rbx
    call    std::ctype<char>::_M_widen_init() const
    mov rax, QWORD PTR [rbx]
    lea rcx, std::ctype<char>::do_widen(char) const[rip]
    mov edx, 10
    mov rax, QWORD PTR 48[rax]
    cmp rax, rcx
    je  .L83
    mov rcx, rbx
    call    rax
    movsx   edx, al
    jmp .L83
.L85:
    call    std::__throw_bad_cast()
    nop
    .seh_endproc
    .text
    .align 2
    .p2align 4,,15
    .globl  int CTQL::dummy_db::get<int>(unsigned int) const
    .def    int CTQL::dummy_db::get<int>(unsigned int) const;   .scl    2;  .type   32; .endef
    .seh_proc   int CTQL::dummy_db::get<int>(unsigned int) const
int CTQL::dummy_db::get<int>(unsigned int) const:
.LFB1970:
    push    rdi
    .seh_pushreg    rdi
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 32
    .seh_stackalloc 32
    .seh_endprologue
    mov r8d, 8
    mov rdi, rcx
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    mov ebx, edx
    lea rdx, .LC6[rip]
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    lea rdx, .LC2[rip]
    mov r8d, 1
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    mov edx, ebx
    call    std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<unsigned long>(unsigned long)
    lea rdx, .LC2[rip]
    mov r8d, 1
    mov rcx, rax
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rax, QWORD PTR .refptr._ZSt4cout[rip]
    mov rdx, QWORD PTR [rax]
    mov rdx, QWORD PTR -24[rdx]
    mov rsi, QWORD PTR 240[rdx+rax]
    test    rsi, rsi
    je  .L91
    cmp BYTE PTR 56[rsi], 0
    je  .L88
    movsx   edx, BYTE PTR 67[rsi]
.L89:
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    imul    ebx, ebx, 100
    call    std::basic_ostream<char, std::char_traits<char> >::put(char)
    mov rcx, rax
    call    std::basic_ostream<char, std::char_traits<char> >::flush()
    mov eax, DWORD PTR [rdi]
    lea eax, [rax+rax*4]
    lea eax, [rbx+rax*2]
    add rsp, 32
    pop rbx
    pop rsi
    pop rdi
    ret
    .p2align 4,,10
.L88:
    mov rcx, rsi
    call    std::ctype<char>::_M_widen_init() const
    mov rax, QWORD PTR [rsi]
    lea rcx, std::ctype<char>::do_widen(char) const[rip]
    mov edx, 10
    mov rax, QWORD PTR 48[rax]
    cmp rax, rcx
    je  .L89
    mov rcx, rsi
    call    rax
    movsx   edx, al
    jmp .L89
.L91:
    call    std::__throw_bad_cast()
    nop
    .seh_endproc
    .align 2
    .p2align 4,,15
    .globl  double CTQL::dummy_db::get<double>(unsigned int) const
    .def    double CTQL::dummy_db::get<double>(unsigned int) const; .scl    2;  .type   32; .endef
    .seh_proc   double CTQL::dummy_db::get<double>(unsigned int) const
double CTQL::dummy_db::get<double>(unsigned int) const:
.LFB1971:
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 40
    .seh_stackalloc 40
    .seh_endprologue
    mov r8d, 11
    mov rsi, rcx
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    mov ebx, edx
    lea rdx, .LC3[rip]
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    lea rdx, .LC2[rip]
    mov r8d, 1
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    mov edx, ebx
    call    std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<unsigned long>(unsigned long)
    lea rdx, .LC2[rip]
    mov r8d, 1
    mov rcx, rax
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov rax, QWORD PTR .refptr._ZSt4cout[rip]
    mov rdx, QWORD PTR [rax]
    mov rdx, QWORD PTR -24[rdx]
    mov rbx, QWORD PTR 240[rdx+rax]
    test    rbx, rbx
    je  .L99
    cmp BYTE PTR 56[rbx], 0
    je  .L94
    movsx   edx, BYTE PTR 67[rbx]
.L95:
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
    call    std::basic_ostream<char, std::char_traits<char> >::put(char)
    mov rcx, rax
    call    std::basic_ostream<char, std::char_traits<char> >::flush()
    mov eax, DWORD PTR [rsi]
    pxor    xmm0, xmm0
    cvtsi2sdq   xmm0, rax
    mulsd   xmm0, QWORD PTR .LC4[rip]
    addsd   xmm0, QWORD PTR .LC5[rip]
    add rsp, 40
    pop rbx
    pop rsi
    ret
    .p2align 4,,10
.L94:
    mov rcx, rbx
    call    std::ctype<char>::_M_widen_init() const
    mov rax, QWORD PTR [rbx]
    lea rcx, std::ctype<char>::do_widen(char) const[rip]
    mov edx, 10
    mov rax, QWORD PTR 48[rax]
    cmp rax, rcx
    je  .L95
    mov rcx, rbx
    call    rax
    movsx   edx, al
    jmp .L95
.L99:
    call    std::__throw_bad_cast()
    nop
    .seh_endproc
    .section .rdata,"dr"
    .align 8
.LC9:
    .ascii "SELECT foo.value, foo.id, foo.number FROM foo WHERE foo.id>42\0"
    .text
    .p2align 4,,15
    .globl  handwritten()
    .def    handwritten();  .scl    2;  .type   32; .endef
    .seh_proc   handwritten()
handwritten():
.LFB2021:
    push    r12
    .seh_pushreg    r12
    push    rbp
    .seh_pushreg    rbp
    push    rdi
    .seh_pushreg    rdi
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 64
    .seh_stackalloc 64
    .seh_endprologue
    lea rbx, 32[rsp]
    mov rdi, rcx
    call    CTQL::vector_noinline<handwritten()::Row>::vector_noinline()
    lea rdx, .LC9[rip]
    mov rcx, rbx
    mov DWORD PTR 32[rsp], 0
.LEHB0:
    call    CTQL::dummy_db::execute(char const*)
    call    CTQL::dummy_db::read_count() const [clone .isra.32]
    mov edx, eax
    mov rcx, rdi
    mov rbp, rdx
    call    CTQL::vector_noinline<handwritten()::Row>::reserve(unsigned long) [clone .constprop.34]
    test    ebp, ebp
    je  .L100
    lea r12, 48[rsp]
    xor esi, esi
    .p2align 4,,10
.L103:
    mov rcx, rbx
    call    double CTQL::dummy_db::get<double>(unsigned int) const [clone .constprop.40]
    mov rcx, rbx
    movsd   QWORD PTR 48[rsp], xmm0
    call    int CTQL::dummy_db::get<int>(unsigned int) const [clone .constprop.41]
    mov rcx, rbx
    mov DWORD PTR 56[rsp], eax
    call    int CTQL::dummy_db::get<int>(unsigned int) const [clone .constprop.42]
    mov rdx, r12
    mov rcx, rdi
    mov DWORD PTR 60[rsp], eax
    call    CTQL::vector_noinline<handwritten()::Row>::push_back(handwritten()::Row const&) [clone .constprop.36]
    mov rcx, rbx
    add esi, 1
    call    CTQL::dummy_db::move_to_next()
.LEHE0:
    cmp ebp, esi
    jne .L103
.L100:
    mov rax, rdi
    add rsp, 64
    pop rbx
    pop rsi
    pop rdi
    pop rbp
    pop r12
    ret
.L106:
    mov rbx, rax
    mov rcx, rdi
    call    CTQL::vector_noinline<handwritten()::Row>::~vector_noinline()
    mov rcx, rbx
.LEHB1:
    call    _Unwind_Resume
    nop
.LEHE1:
    .def    __gxx_personality_seh0; .scl    2;  .type   32; .endef
    .seh_handler    __gxx_personality_seh0, @unwind, @except
    .seh_handlerdata
.LLSDA2021:
    .byte   0xff
    .byte   0xff
    .byte   0x1
    .uleb128 .LLSDACSE2021-.LLSDACSB2021
.LLSDACSB2021:
    .uleb128 .LEHB0-.LFB2021
    .uleb128 .LEHE0-.LEHB0
    .uleb128 .L106-.LFB2021
    .uleb128 0
    .uleb128 .LEHB1-.LFB2021
    .uleb128 .LEHE1-.LEHB1
    .uleb128 0
    .uleb128 0
.LLSDACSE2021:
    .text
    .seh_endproc
    .section    .text$_ZN4CTQL15vector_noinlineINS_8make_rowIJNS_12table_columnI7foo_auxdNS3_12value_column11field_valueEEENS2_IS3_iNS3_9id_column8field_idEEENS2_IS3_iNS3_13number_column12field_numberEEEEEEEC1Ev,"x"
    .linkonce discard
    .align 2
    .p2align 4,,15
    .globl  CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline()
    .def    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline();    .scl    2;  .type   32; .endef
    .seh_proc   CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline()
CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline():
.LFB2128:
    .seh_endprologue
    mov QWORD PTR [rcx], 0
    mov QWORD PTR 8[rcx], 0
    mov QWORD PTR 16[rcx], 0
    ret
    .seh_endproc
    .weak   CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline()
    .def    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline();    .scl    2;  .type   32; .endef
    .set    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline(),CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline()
    .section    .text$_ZN4CTQL15vector_noinlineINS_8make_rowIJNS_12table_columnI7foo_auxdNS3_12value_column11field_valueEEENS2_IS3_iNS3_9id_column8field_idEEENS2_IS3_iNS3_13number_column12field_numberEEEEEEED1Ev,"x"
    .linkonce discard
    .align 2
    .p2align 4,,15
    .globl  CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline()
    .def    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline();   .scl    2;  .type   32; .endef
    .seh_proc   CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline()
CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline():
.LFB2131:
    .seh_endprologue
    mov rcx, QWORD PTR [rcx]
    test    rcx, rcx
    je  .L113
    jmp operator delete(void*)
    .p2align 4,,10
.L113:
    rep ret
    .seh_endproc
    .weak   CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline()
    .def    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline();   .scl    2;  .type   32; .endef
    .set    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline(),CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline()
    .section    .text$_ZN4CTQL15vector_noinlineINS_8make_rowIJNS_12table_columnI7foo_auxdNS3_12value_column11field_valueEEENS2_IS3_iNS3_9id_column8field_idEEENS2_IS3_iNS3_13number_column12field_numberEEEEEEE7reserveEm,"x"
    .linkonce discard
    .align 2
    .p2align 4,,15
    .globl  CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long)
    .def    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long);   .scl    2;  .type   32; .endef
    .seh_proc   CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long)
CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long):
.LFB2273:
    push    r13
    .seh_pushreg    r13
    push    r12
    .seh_pushreg    r12
    push    rbp
    .seh_pushreg    rbp
    push    rdi
    .seh_pushreg    rdi
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 40
    .seh_stackalloc 40
    .seh_endprologue
    movabs  rax, 1152921504606846975
    cmp rdx, rax
    mov rsi, rcx
    ja  .L126
    mov rbp, QWORD PTR [rcx]
    mov rax, QWORD PTR 16[rcx]
    sub rax, rbp
    sar rax, 4
    cmp rdx, rax
    ja  .L127
    add rsp, 40
    pop rbx
    pop rsi
    pop rdi
    pop rbp
    pop r12
    pop r13
    ret
    .p2align 4,,10
.L127:
    mov rdi, QWORD PTR 8[rcx]
    sub rdi, rbp
    test    rdx, rdx
    je  .L122
    mov rbx, rdx
    sal rbx, 4
    mov rcx, rbx
    call    operator new(unsigned long)
    mov r13, QWORD PTR [rsi]
    mov r12, rax
.L118:
    mov rax, rdi
    sar rax, 4
    test    rax, rax
    je  .L120
    mov r8, rdi
    mov rdx, rbp
    mov rcx, r12
    call    memmove
.L120:
    test    r13, r13
    je  .L121
    mov rcx, r13
    call    operator delete(void*)
.L121:
    lea rdx, [r12+rbx]
    add rdi, r12
    mov QWORD PTR [rsi], r12
    mov QWORD PTR 8[rsi], rdi
    mov QWORD PTR 16[rsi], rdx
    add rsp, 40
    pop rbx
    pop rsi
    pop rdi
    pop rbp
    pop r12
    pop r13
    ret
    .p2align 4,,10
.L122:
    mov r13, rbp
    xor ebx, ebx
    xor r12d, r12d
    jmp .L118
.L126:
    lea rcx, .LC0[rip]
    call    std::__throw_length_error(char const*)
    nop
    .seh_endproc
    .weak   CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long)
    .def    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long);   .scl    2;  .type   32; .endef
    .set    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long),CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long)
    .section .rdata,"dr"
.LC10:
    .ascii "ROW: \0"
    .section    .text$_Z5printIN4CTQL15vector_noinlineINS0_8make_rowIJNS0_12table_columnI7foo_auxdNS4_12value_column11field_valueEEENS3_IS4_iNS4_9id_column8field_idEEENS3_IS4_iNS4_13number_column12field_numberEEEEEEEEEvOT_,"x"
    .linkonce discard
    .p2align 4,,15
    .globl  void print<CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&)
    .def    void print<CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&);  .scl    2;  .type   32; .endef
    .seh_proc   void print<CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&)
void print<CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&):
.LFB2280:
    push    r14
    .seh_pushreg    r14
    push    r13
    .seh_pushreg    r13
    push    r12
    .seh_pushreg    r12
    push    rbp
    .seh_pushreg    rbp
    push    rdi
    .seh_pushreg    rdi
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 48
    .seh_stackalloc 48
    movaps  XMMWORD PTR 32[rsp], xmm6
    .seh_savexmm    xmm6, 32
    .seh_endprologue
    mov rbx, QWORD PTR [rcx]
    mov rbp, QWORD PTR 8[rcx]
    cmp rbx, rbp
    je  .L128
    mov r12, QWORD PTR .refptr._ZSt4cout[rip]
    lea r14, std::ctype<char>::do_widen(char) const[rip]
    mov r13, r12
    jmp .L136
    .p2align 4,,10
.L139:
    movsx   edx, BYTE PTR 67[rsi]
.L132:
    mov rcx, rdi
    add rbx, 16
    call    std::basic_ostream<char, std::char_traits<char> >::put(char)
    mov rcx, rax
    call    std::basic_ostream<char, std::char_traits<char> >::flush()
    cmp rbp, rbx
    je  .L128
.L136:
    mov esi, DWORD PTR 8[rbx]
    lea rdx, .LC10[rip]
    mov r8d, 5
    mov rcx, r12
    mov edi, DWORD PTR 12[rbx]
    movsd   xmm6, QWORD PTR [rbx]
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov edx, esi
    mov rcx, r13
    call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
    lea rdx, .LC2[rip]
    mov r8d, 1
    mov rcx, rax
    mov rsi, rax
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    movapd  xmm1, xmm6
    mov rcx, rsi
    call    std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<double>(double)
    lea rdx, .LC2[rip]
    mov rsi, rax
    mov r8d, 1
    mov rcx, rax
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov edx, edi
    mov rcx, rsi
    call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
    mov rdi, rax
    mov rax, QWORD PTR [rax]
    mov rax, QWORD PTR -24[rax]
    mov rsi, QWORD PTR 240[rdi+rax]
    test    rsi, rsi
    je  .L138
    cmp BYTE PTR 56[rsi], 0
    jne .L139
    mov rcx, rsi
    call    std::ctype<char>::_M_widen_init() const
    mov rax, QWORD PTR [rsi]
    mov edx, 10
    mov rax, QWORD PTR 48[rax]
    cmp rax, r14
    je  .L132
    mov rcx, rsi
    call    rax
    movsx   edx, al
    jmp .L132
    .p2align 4,,10
.L128:
    movaps  xmm6, XMMWORD PTR 32[rsp]
    add rsp, 48
    pop rbx
    pop rsi
    pop rdi
    pop rbp
    pop r12
    pop r13
    pop r14
    ret
.L138:
    call    std::__throw_bad_cast()
    nop
    .seh_endproc
    .weak   void print<CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&)
    .def    void print<CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&);  .scl    2;  .type   32; .endef
    .set    void print<CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&),void print<CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&)
    .section    .text$_ZNSt6vectorIN4CTQL8make_rowIJNS0_12table_columnI7foo_auxdNS3_12value_column11field_valueEEENS2_IS3_iNS3_9id_column8field_idEEENS2_IS3_iNS3_13number_column12field_numberEEEEEESaISD_EE19_M_emplace_back_auxIJRKSD_EEEvDpOT_,"x"
    .linkonce discard
    .align 2
    .p2align 4,,15
    .globl  void std::vector<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    .def    void std::vector<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&);  .scl    2;  .type   32; .endef
    .seh_proc   void std::vector<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
void std::vector<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&):
.LFB2493:
    push    r13
    .seh_pushreg    r13
    push    r12
    .seh_pushreg    r12
    push    rbp
    .seh_pushreg    rbp
    push    rdi
    .seh_pushreg    rdi
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 40
    .seh_stackalloc 40
    .seh_endprologue
    mov r8, QWORD PTR 8[rcx]
    mov rbx, rcx
    mov r13, rdx
    mov rax, r8
    sub rax, QWORD PTR [rcx]
    sar rax, 4
    test    rax, rax
    je  .L148
    lea rdx, [rax+rax]
    cmp rax, rdx
    jbe .L159
.L149:
    mov rbp, -16
    jmp .L141
    .p2align 4,,10
.L148:
    mov ebp, 16
.L141:
    mov rcx, rbp
    call    operator new(unsigned long)
    mov r8, QWORD PTR 8[rbx]
    mov rsi, rax
.L147:
    mov r12, QWORD PTR [rbx]
    mov rdi, rsi
    sub r8, r12
    mov rax, r8
    sar rax, 4
    add rdi, r8
    je  .L143
    mov r9, QWORD PTR 0[r13]
    mov r10, QWORD PTR 8[r13]
    mov QWORD PTR [rdi], r9
    mov QWORD PTR 8[rdi], r10
.L143:
    test    rax, rax
    jne .L160
    add rdi, 16
    test    r12, r12
    je  .L146
.L145:
    mov rcx, r12
    call    operator delete(void*)
.L146:
    mov QWORD PTR [rbx], rsi
    add rsi, rbp
    mov QWORD PTR 8[rbx], rdi
    mov QWORD PTR 16[rbx], rsi
    add rsp, 40
    pop rbx
    pop rsi
    pop rdi
    pop rbp
    pop r12
    pop r13
    ret
    .p2align 4,,10
.L160:
    mov rdx, r12
    mov rcx, rsi
    add rdi, 16
    call    memmove
    jmp .L145
.L159:
    movabs  rcx, 1152921504606846975
    cmp rdx, rcx
    ja  .L149
    xor ebp, ebp
    xor esi, esi
    test    rdx, rdx
    je  .L147
    sal rax, 5
    mov rbp, rax
    jmp .L141
    .seh_endproc
    .weak   void std::vector<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    .def    void std::vector<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&);  .scl    2;  .type   32; .endef
    .set    void std::vector<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&),void std::vector<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    .section    .text$_ZN4CTQL15vector_noinlineINS_8make_rowIJNS_12table_columnI7foo_auxdNS3_12value_column11field_valueEEENS2_IS3_iNS3_9id_column8field_idEEENS2_IS3_iNS3_13number_column12field_numberEEEEEEE9push_backERKSD_,"x"
    .linkonce discard
    .align 2
    .p2align 4,,15
    .globl  CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    .def    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&);   .scl    2;  .type   32; .endef
    .seh_proc   CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&):
.LFB2275:
    .seh_endprologue
    mov rax, QWORD PTR 8[rcx]
    cmp rax, QWORD PTR 16[rcx]
    je  .L162
    test    rax, rax
    je  .L163
    mov r9, QWORD PTR [rdx]
    mov r10, QWORD PTR 8[rdx]
    mov QWORD PTR [rax], r9
    mov QWORD PTR 8[rax], r10
.L163:
    add rax, 16
    mov QWORD PTR 8[rcx], rax
    ret
    .p2align 4,,10
.L162:
    jmp void std::vector<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    .seh_endproc
    .weak   CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    .def    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&);   .scl    2;  .type   32; .endef
    .set    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&),CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    .section    .text$_ZN4CTQL9to_vectorINS_10make_tableIN7foo_aux11name_stringEJNS2_9id_columnENS2_11code_columnENS2_12value_columnENS2_13number_columnEEEEKNS_8string_tIJLc102ELc111ELc111ELc46ELc105ELc100ELc62ELc52ELc50EEEEJNS_12table_columnIS2_dNS6_11field_valueEEENSC_IS2_iNS4_8field_idEEENSC_IS2_iNS7_12field_numberEEEEEEDaNS_5queryIT_T0_JDpT1_EEE,"x"
    .linkonce discard
    .p2align 4,,15
    .globl  auto CTQL::to_vector<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >(CTQL::query<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >)
    .def    auto CTQL::to_vector<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >(CTQL::query<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >);  .scl    2;  .type   32; .endef
    .seh_proc   auto CTQL::to_vector<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >(CTQL::query<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >)
auto CTQL::to_vector<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >(CTQL::query<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >):
.LFB2067:
    push    r12
    .seh_pushreg    r12
    push    rbp
    .seh_pushreg    rbp
    push    rdi
    .seh_pushreg    rdi
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 64
    .seh_stackalloc 64
    .seh_endprologue
    lea rbx, 32[rsp]
    mov rdi, rcx
    call    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline()
    lea rdx, CTQL::string_value<(char)83, (char)69, (char)76, (char)69, (char)67, (char)84, (char)32, (char)102, (char)111, (char)111, (char)46, (char)118, (char)97, (char)108, (char)117, (char)101, (char)44, (char)32, (char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)44, (char)32, (char)102, (char)111, (char)111, (char)46, (char)110, (char)117, (char)109, (char)98, (char)101, (char)114, (char)32, (char)70, (char)82, (char)79, (char)77, (char)32, (char)102, (char)111, (char)111, (char)32, (char)87, (char)72, (char)69, (char)82, (char)69, (char)32, (char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50>::value[rip]
    mov rcx, rbx
    mov DWORD PTR 32[rsp], 0
.LEHB2:
    call    CTQL::dummy_db::execute(char const*)
    call    CTQL::dummy_db::read_count() const [clone .isra.32]
    mov edx, eax
    mov rcx, rdi
    mov rbp, rdx
    call    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long)
    test    ebp, ebp
    je  .L169
    lea r12, 48[rsp]
    xor esi, esi
    .p2align 4,,10
.L172:
    mov rcx, rbx
    call    double CTQL::dummy_db::get<double>(unsigned int) const [clone .constprop.40]
    mov rcx, rbx
    movsd   QWORD PTR 48[rsp], xmm0
    call    int CTQL::dummy_db::get<int>(unsigned int) const [clone .constprop.41]
    mov rcx, rbx
    mov DWORD PTR 56[rsp], eax
    call    int CTQL::dummy_db::get<int>(unsigned int) const [clone .constprop.42]
    mov rdx, r12
    mov rcx, rdi
    mov DWORD PTR 60[rsp], eax
    call    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    mov rcx, rbx
    add esi, 1
    call    CTQL::dummy_db::move_to_next()
.LEHE2:
    cmp ebp, esi
    jne .L172
.L169:
    mov rax, rdi
    add rsp, 64
    pop rbx
    pop rsi
    pop rdi
    pop rbp
    pop r12
    ret
.L175:
    mov rbx, rax
    mov rcx, rdi
    call    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline()
    mov rcx, rbx
.LEHB3:
    call    _Unwind_Resume
    nop
.LEHE3:
    .seh_handler    __gxx_personality_seh0, @unwind, @except
    .seh_handlerdata
.LLSDA2067:
    .byte   0xff
    .byte   0xff
    .byte   0x1
    .uleb128 .LLSDACSE2067-.LLSDACSB2067
.LLSDACSB2067:
    .uleb128 .LEHB2-.LFB2067
    .uleb128 .LEHE2-.LEHB2
    .uleb128 .L175-.LFB2067
    .uleb128 0
    .uleb128 .LEHB3-.LFB2067
    .uleb128 .LEHE3-.LEHB3
    .uleb128 0
    .uleb128 0
.LLSDACSE2067:
    .section    .text$_ZN4CTQL9to_vectorINS_10make_tableIN7foo_aux11name_stringEJNS2_9id_columnENS2_11code_columnENS2_12value_columnENS2_13number_columnEEEEKNS_8string_tIJLc102ELc111ELc111ELc46ELc105ELc100ELc62ELc52ELc50EEEEJNS_12table_columnIS2_dNS6_11field_valueEEENSC_IS2_iNS4_8field_idEEENSC_IS2_iNS7_12field_numberEEEEEEDaNS_5queryIT_T0_JDpT1_EEE,"x"
    .linkonce discard
    .seh_endproc
    .weak   auto CTQL::to_vector<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >(CTQL::query<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >)
    .def    auto CTQL::to_vector<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >(CTQL::query<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >); .scl    2;  .type   32; .endef
    .set    auto CTQL::to_vector<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >(CTQL::query<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >),auto CTQL::to_vector<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >(CTQL::query<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >)
    .def    __main; .scl    2;  .type   32; .endef
    .section    .text.startup,"x"
    .p2align 4,,15
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
.LFB2035:
    push    r15
    .seh_pushreg    r15
    push    r14
    .seh_pushreg    r14
    push    r13
    .seh_pushreg    r13
    push    r12
    .seh_pushreg    r12
    push    rbp
    .seh_pushreg    rbp
    push    rdi
    .seh_pushreg    rdi
    push    rsi
    .seh_pushreg    rsi
    push    rbx
    .seh_pushreg    rbx
    sub rsp, 88
    .seh_stackalloc 88
    movaps  XMMWORD PTR 64[rsp], xmm6
    .seh_savexmm    xmm6, 64
    .seh_endprologue
    lea r14, 32[rsp]
    call    __main
    mov rcx, r14
    xor edx, edx
.LEHB4:
    call    auto CTQL::to_vector<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >(CTQL::query<CTQL::make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, CTQL::string_t<(char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50> const, CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> >)
.LEHE4:
    mov rcx, r14
.LEHB5:
    call    void print<CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&)
.LEHE5:
    mov rcx, r14
    call    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline()
    mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
.LEHB6:
    call    std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
    mov rcx, r14
    call    handwritten()
.LEHE6:
    mov rbx, QWORD PTR 32[rsp]
    mov rbp, QWORD PTR 40[rsp]
    cmp rbx, rbp
    je  .L187
    mov r12, QWORD PTR .refptr._ZSt4cout[rip]
    lea r15, std::ctype<char>::do_widen(char) const[rip]
    mov r13, r12
    jmp .L193
    .p2align 4,,10
.L197:
    movsx   edx, BYTE PTR 67[rsi]
.L185:
    mov rcx, rdi
.LEHB7:
    call    std::basic_ostream<char, std::char_traits<char> >::put(char)
    mov rcx, rax
    call    std::basic_ostream<char, std::char_traits<char> >::flush()
    add rbx, 16
    cmp rbp, rbx
    je  .L187
.L193:
    lea rdx, .LC10[rip]
    mov r8d, 5
    mov rcx, r12
    mov edi, DWORD PTR 12[rbx]
    movsd   xmm6, QWORD PTR [rbx]
    mov esi, DWORD PTR 8[rbx]
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov edx, esi
    mov rcx, r13
    call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
    lea rdx, .LC2[rip]
    mov r8d, 1
    mov rcx, rax
    mov rsi, rax
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    movapd  xmm1, xmm6
    mov rcx, rsi
    call    std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<double>(double)
    lea rdx, .LC2[rip]
    mov r8d, 1
    mov rcx, rax
    mov rsi, rax
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    mov edx, edi
    mov rcx, rsi
    call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
    mov rdi, rax
    mov rax, QWORD PTR [rax]
    mov rax, QWORD PTR -24[rax]
    mov rsi, QWORD PTR 240[rdi+rax]
    test    rsi, rsi
    je  .L196
    cmp BYTE PTR 56[rsi], 0
    jne .L197
    mov rcx, rsi
    call    std::ctype<char>::_M_widen_init() const
    mov rax, QWORD PTR [rsi]
    mov edx, 10
    mov rax, QWORD PTR 48[rax]
    cmp rax, r15
    je  .L185
    mov rcx, rsi
    call    rax
    movsx   edx, al
    jmp .L185
    .p2align 4,,10
.L187:
    mov rcx, r14
    call    CTQL::vector_noinline<handwritten()::Row>::~vector_noinline()
    nop
    movaps  xmm6, XMMWORD PTR 64[rsp]
    xor eax, eax
    add rsp, 88
    pop rbx
    pop rsi
    pop rdi
    pop rbp
    pop r12
    pop r13
    pop r14
    pop r15
    ret
.L196:
    call    std::__throw_bad_cast()
.LEHE7:
.L192:
    mov rbx, rax
    mov rcx, r14
    call    CTQL::vector_noinline<handwritten()::Row>::~vector_noinline()
    mov rcx, rbx
.LEHB8:
    call    _Unwind_Resume
.L191:
    mov rbx, rax
    mov rcx, r14
    call    CTQL::vector_noinline<CTQL::make_row<CTQL::table_column<foo_aux, double, foo_aux::value_column::field_value>, CTQL::table_column<foo_aux, int, foo_aux::id_column::field_id>, CTQL::table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline()
    mov rcx, rbx
    call    _Unwind_Resume
    nop
.LEHE8:
    .seh_handler    __gxx_personality_seh0, @unwind, @except
    .seh_handlerdata
.LLSDA2035:
    .byte   0xff
    .byte   0xff
    .byte   0x1
    .uleb128 .LLSDACSE2035-.LLSDACSB2035
.LLSDACSB2035:
    .uleb128 .LEHB4-.LFB2035
    .uleb128 .LEHE4-.LEHB4
    .uleb128 0
    .uleb128 0
    .uleb128 .LEHB5-.LFB2035
    .uleb128 .LEHE5-.LEHB5
    .uleb128 .L191-.LFB2035
    .uleb128 0
    .uleb128 .LEHB6-.LFB2035
    .uleb128 .LEHE6-.LEHB6
    .uleb128 0
    .uleb128 0
    .uleb128 .LEHB7-.LFB2035
    .uleb128 .LEHE7-.LEHB7
    .uleb128 .L192-.LFB2035
    .uleb128 0
    .uleb128 .LEHB8-.LFB2035
    .uleb128 .LEHE8-.LEHB8
    .uleb128 0
    .uleb128 0
.LLSDACSE2035:
    .section    .text.startup,"x"
    .seh_endproc
    .p2align 4,,15
    .def    _GLOBAL__sub_I__ZNK4CTQL8dummy_db3getIiEET_j;   .scl    3;  .type   32; .endef
    .seh_proc   _GLOBAL__sub_I__ZNK4CTQL8dummy_db3getIiEET_j
_GLOBAL__sub_I__ZNK4CTQL8dummy_db3getIiEET_j:
.LFB2663:
    sub rsp, 40
    .seh_stackalloc 40
    .seh_endprologue
    lea rcx, std::__ioinit[rip]
    call    std::ios_base::Init::Init()
    mov r8, QWORD PTR .refptr.__dso_handle[rip]
    lea rdx, std::__ioinit[rip]
    lea rcx, std::ios_base::Init::~Init()[rip]
    add rsp, 40
    jmp __cxa_atexit
    .seh_endproc
    .section    .ctors,"w"
    .align 8
    .quad   _GLOBAL__sub_I__ZNK4CTQL8dummy_db3getIiEET_j
    .globl  CTQL::string_value<(char)83, (char)69, (char)76, (char)69, (char)67, (char)84, (char)32, (char)102, (char)111, (char)111, (char)46, (char)118, (char)97, (char)108, (char)117, (char)101, (char)44, (char)32, (char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)44, (char)32, (char)102, (char)111, (char)111, (char)46, (char)110, (char)117, (char)109, (char)98, (char)101, (char)114, (char)32, (char)70, (char)82, (char)79, (char)77, (char)32, (char)102, (char)111, (char)111, (char)32, (char)87, (char)72, (char)69, (char)82, (char)69, (char)32, (char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50>::value
    .section    .rdata$_ZN4CTQL12string_valueIJLc83ELc69ELc76ELc69ELc67ELc84ELc32ELc102ELc111ELc111ELc46ELc118ELc97ELc108ELc117ELc101ELc44ELc32ELc102ELc111ELc111ELc46ELc105ELc100ELc44ELc32ELc102ELc111ELc111ELc46ELc110ELc117ELc109ELc98ELc101ELc114ELc32ELc70ELc82ELc79ELc77ELc32ELc102ELc111ELc111ELc32ELc87ELc72ELc69ELc82ELc69ELc32ELc102ELc111ELc111ELc46ELc105ELc100ELc62ELc52ELc50EEE5valueE,"dr"
    .linkonce same_size
    .align 32
CTQL::string_value<(char)83, (char)69, (char)76, (char)69, (char)67, (char)84, (char)32, (char)102, (char)111, (char)111, (char)46, (char)118, (char)97, (char)108, (char)117, (char)101, (char)44, (char)32, (char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)44, (char)32, (char)102, (char)111, (char)111, (char)46, (char)110, (char)117, (char)109, (char)98, (char)101, (char)114, (char)32, (char)70, (char)82, (char)79, (char)77, (char)32, (char)102, (char)111, (char)111, (char)32, (char)87, (char)72, (char)69, (char)82, (char)69, (char)32, (char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50>::value:
    .byte   83
    .byte   69
    .byte   76
    .byte   69
    .byte   67
    .byte   84
    .byte   32
    .byte   102
    .byte   111
    .byte   111
    .byte   46
    .byte   118
    .byte   97
    .byte   108
    .byte   117
    .byte   101
    .byte   44
    .byte   32
    .byte   102
    .byte   111
    .byte   111
    .byte   46
    .byte   105
    .byte   100
    .byte   44
    .byte   32
    .byte   102
    .byte   111
    .byte   111
    .byte   46
    .byte   110
    .byte   117
    .byte   109
    .byte   98
    .byte   101
    .byte   114
    .byte   32
    .byte   70
    .byte   82
    .byte   79
    .byte   77
    .byte   32
    .byte   102
    .byte   111
    .byte   111
    .byte   32
    .byte   87
    .byte   72
    .byte   69
    .byte   82
    .byte   69
    .byte   32
    .byte   102
    .byte   111
    .byte   111
    .byte   46
    .byte   105
    .byte   100
    .byte   62
    .byte   52
    .byte   50
    .byte   0
    .globl  CTQL::string_value<(char)83, (char)69, (char)76, (char)69, (char)67, (char)84, (char)32, (char)102, (char)111, (char)111, (char)46, (char)118, (char)97, (char)108, (char)117, (char)101, (char)44, (char)32, (char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)44, (char)32, (char)102, (char)111, (char)111, (char)46, (char)110, (char)117, (char)109, (char)98, (char)101, (char)114, (char)32, (char)70, (char)82, (char)79, (char)77, (char)32, (char)102, (char)111, (char)111, (char)32, (char)87, (char)72, (char)69, (char)82, (char)69, (char)32, (char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50>::value
    .set    CTQL::string_value<(char)83, (char)69, (char)76, (char)69, (char)67, (char)84, (char)32, (char)102, (char)111, (char)111, (char)46, (char)118, (char)97, (char)108, (char)117, (char)101, (char)44, (char)32, (char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)44, (char)32, (char)102, (char)111, (char)111, (char)46, (char)110, (char)117, (char)109, (char)98, (char)101, (char)114, (char)32, (char)70, (char)82, (char)79, (char)77, (char)32, (char)102, (char)111, (char)111, (char)32, (char)87, (char)72, (char)69, (char)82, (char)69, (char)32, (char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50>::value,CTQL::string_value<(char)83, (char)69, (char)76, (char)69, (char)67, (char)84, (char)32, (char)102, (char)111, (char)111, (char)46, (char)118, (char)97, (char)108, (char)117, (char)101, (char)44, (char)32, (char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)44, (char)32, (char)102, (char)111, (char)111, (char)46, (char)110, (char)117, (char)109, (char)98, (char)101, (char)114, (char)32, (char)70, (char)82, (char)79, (char)77, (char)32, (char)102, (char)111, (char)111, (char)32, (char)87, (char)72, (char)69, (char)82, (char)69, (char)32, (char)102, (char)111, (char)111, (char)46, (char)105, (char)100, (char)62, (char)52, (char)50>::value
    .globl  foo
    .bss
foo:
    .space 4
.lcomm std::__ioinit,1,1
    .section .rdata,"dr"
    .align 8
.LC4:
    .long   1202590843
    .long   1065646817
    .align 8
.LC5:
    .long   0
    .long   1072693248
    .ident  "GCC: (GNU) 5.3.0"
    .def    __real__ZdlPv;  .scl    2;  .type   32; .endef
    .def    operator delete(void*); .scl    2;  .type   32; .endef
    .def    __real__Znwm;   .scl    2;  .type   32; .endef
    .def    operator new(unsigned long);    .scl    2;  .type   32; .endef
    .def    memmove;    .scl    2;  .type   32; .endef
    .def    std::__throw_length_error(char const*); .scl    2;  .type   32; .endef
    .def    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long); .scl    2;  .type   32; .endef
    .def    std::basic_ostream<char, std::char_traits<char> >::put(char);   .scl    2;  .type   32; .endef
    .def    std::basic_ostream<char, std::char_traits<char> >::flush(); .scl    2;  .type   32; .endef
    .def    std::ctype<char>::_M_widen_init() const;    .scl    2;  .type   32; .endef
    .def    std::__throw_bad_cast();    .scl    2;  .type   32; .endef
    .def    std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<unsigned long>(unsigned long);  .scl    2;  .type   32; .endef
    .def    strlen; .scl    2;  .type   32; .endef
    .def    std::basic_ios<char, std::char_traits<char> >::clear(std::_Ios_Iostate);    .scl    2;  .type   32; .endef
    .def    _Unwind_Resume; .scl    2;  .type   32; .endef
    .def    std::basic_ostream<char, std::char_traits<char> >::operator<<(int); .scl    2;  .type   32; .endef
    .def    std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<double>(double);    .scl    2;  .type   32; .endef
    .def    std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&);    .scl    2;  .type   32; .endef
    .def    std::ios_base::Init::Init();    .scl    2;  .type   32; .endef
    .def    std::ios_base::Init::~Init();   .scl    2;  .type   32; .endef
    .def    __cxa_atexit;   .scl    2;  .type   32; .endef
    .section    .rdata$.refptr._ZNSt8ios_base4InitD1Ev, "dr"
    .globl  .refptr._ZNSt8ios_base4InitD1Ev
    .linkonce   discard
.refptr._ZNSt8ios_base4InitD1Ev:
    .quad   std::ios_base::Init::~Init()
    .section    .rdata$.refptr.__dso_handle, "dr"
    .globl  .refptr.__dso_handle
    .linkonce   discard
.refptr.__dso_handle:
    .quad   __dso_handle
    .section    .rdata$.refptr._ZSt4cout, "dr"
    .globl  .refptr._ZSt4cout
    .linkonce   discard
.refptr._ZSt4cout:
    .quad   std::cout

Hana-style

Метапрограммирование в примерах выше — в стиле Hana.
Саму Boost.Hana не использовал так как её пока нет на Coliru, а хотелось сделать полноценное Live Demo. С ней конечно же кода было бы меньше, так как многие необходимые компоненты типа конкатенации уже готовы.

Compile-time Pattern Matching

В C++ перегрузка функций, так же как и специализация шаблонов, позволяет делать Pattern Matching по структуре дерева выражения запроса. Что помогает выражать оптимизации в коде.
Для примера возьмём запрос:
auto q = from
(
    from
    (
        from(foo).where(foo.id > 40_i).select(foo.id)
    ).where(foo.id > 41_i).select(foo.id)
).where(foo.id > 42_i).select(foo.id);

Изначально генерируется следующий код (условия тестовые, пока нет псевдонимов, но не суть):
SELECT foo.id FROM
(
    SELECT foo.id FROM
    (
        SELECT foo.id FROM foo WHERE foo.id>40
    ) WHERE foo.id>41
) WHERE foo.id>42

Этот код генерирует функция make_sql:
template<typename Source, typename Condition, typename ...Columns>
constexpr auto make_sql
(
    Source source,
    Condition condition,
    Columns... columns
)
{
    return concat
    (
        CTQL_STRING("SELECT "), concat_columns(columns...),
        CTQL_STRING(" FROM "), source_string(source),
        skip_if_empty(condition, concat(CTQL_STRING(" WHERE "), condition))
    );
}

Добавляем перегрузку для запросов с подзапросом во FROM, что по сути является PM времени компиляции:
template
<
    typename SubSource, typename SubCondition, typename ...SubColumns,
    typename Condition, typename ...Columns
>
constexpr auto make_sql
(
    query<SubSource, SubCondition, SubColumns...>,
    Condition condition,
    Columns... columns
)
{
    return make_sql
    (
        SubSource{},
        concat(condition, CTQL_STRING(" AND "), SubCondition{}),
        columns...
    );
}

Эта перегрузка разбирает внутренний запрос, делает внутренний FROM внешним, и склеивает условия, после чего уходит в рекурсию.
При наличии такой перегрузки генерируемый запрос приобретает вид:
SELECT foo.id FROM foo WHERE foo.id>42 AND foo.id>41 AND foo.id>40

Паттерн естественно может быть и более "многоэтажным", для более глубокого матчинга по дереву выражения.
Отредактировано 26.10.2020 11:56 Evgeny.Panasyuk . Предыдущая версия .
Re: [proof-of-concept] compile time query language
От: niXman Ниоткуда https://github.com/niXman
Дата: 11.07.16 19:09
Оценка:
так вроде уже есть: https://github.com/rbock/sqlpp11
текст запросов строится в компайл-тайм.

я писал препроцессорный генератор табличек. сейчас работаю над шаблонным.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Отредактировано 11.07.2016 19:10 niXman . Предыдущая версия .
Re[2]: [proof-of-concept] compile time query language
От: Evgeny.Panasyuk Россия  
Дата: 11.07.16 19:15
Оценка:
Здравствуйте, niXman, Вы писали:

X>так вроде уже есть: https://github.com/rbock/sqlpp11


Я видел, это в том числе обсуждалось в исходной КСВ теме.

X>текст запросов строится в компайл-тайм.


ЕМНИП — нет, и даже есть кое-какой overhead, если ничего не путаю.
В любом случае, сравнения выхлопа ASM с ручной версией я там не видел.

X>я писал препроцессорный генератор табличек. сейчас работаю над шаблонным.


Я не знаю насколько нужен подобный генератор внутри языка. Ведь часто нужно обратиться к уже готовой базе, а для этого нужна внешняя кодогенерация с опросом схемы.
Отредактировано 11.07.2016 19:16 Evgeny.Panasyuk . Предыдущая версия .
Re[2]: [proof-of-concept] compile time query language
От: Evgeny.Panasyuk Россия  
Дата: 11.07.16 19:25
Оценка: +1
Здравствуйте, niXman, Вы писали:

X>текст запросов строится в компайл-тайм.


Вот же:
static Context& _(const T&, Context& context)
{
    context << "SELECT ";
    return context;
}

Это runtime.
Re[3]: [proof-of-concept] compile time query language
От: niXman Ниоткуда https://github.com/niXman
Дата: 11.07.16 19:28
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Я видел, это в том числе обсуждалось в исходной КСВ теме.

я не знаю, что такое КСВ, и не знал, что там это обсуждалось.

EP>ЕМНИП — нет, и даже есть кое-какой overhead, если ничего не путаю.

EP>В любом случае, сравнения выхлопа ASM с ручной версией я там не видел.
ну хз...возможно ошибаюсь...

EP>Я не знаю насколько нужен подобный генератор внутри языка. Ведь часто нужно обратиться к уже готовой базе, а для этого нужна внешняя кодогенерация с опросом схемы.

часто, но не всегда.
мне, к примеру, не интересно создавать БД в каком-то редакторе БД, когда я могу из программы это сделать.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[3]: [proof-of-concept] compile time query language
От: niXman Ниоткуда https://github.com/niXman
Дата: 11.07.16 19:30
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Вот же:

EP>
EP>static Context& _(const T&, Context& context)
EP>{
EP>    context << "SELECT ";
EP>    return context;
EP>}
EP>

EP>Это runtime.

ага, точно. т.е. в компайл-тайме производятся всякие проверки, но сам текст запроса в ран-тайме. ясно.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Отредактировано 11.07.2016 19:31 niXman . Предыдущая версия .
Re[4]: [proof-of-concept] compile time query language
От: Evgeny.Panasyuk Россия  
Дата: 11.07.16 19:35
Оценка:
Здравствуйте, niXman, Вы писали:

EP>>Я видел, это в том числе обсуждалось в исходной КСВ теме.

X>я не знаю, что такое КСВ, и не знал, что там это обсуждалось.

Под-раздел "Компьютерные священные войны". Сама тема
Автор: alex_public
Дата: 17.03.16
. Год назад кстати была подобная тема
Автор: gandjustas
Дата: 15.04.15
.

X>мне, к примеру, не интересно создавать БД в каком-то редакторе БД, когда я могу из программы это сделать.


Ок, а как ты собрался без макросов это делать? Интересует вот эта часть.
Re[4]: [proof-of-concept] compile time query language
От: Evgeny.Panasyuk Россия  
Дата: 11.07.16 19:37
Оценка: +1
Здравствуйте, niXman, Вы писали:

X>ага, точно. т.е. в компайл-тайме производятся всякие проверки, но сам текст запроса в ран-тайме. ясно.


Именно так. Мне же было интересно сделать пример на тему нулевых накладных расходов.
Отредактировано 11.07.2016 19:37 Evgeny.Panasyuk . Предыдущая версия .
Re[5]: [proof-of-concept] compile time query language
От: niXman Ниоткуда https://github.com/niXman
Дата: 11.07.16 19:39
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Ок, а как ты собрался без макросов это делать? Интересует вот эта часть.


или я не понял вопрос, или понял...

без макросов? это ты о том, над чем я сейчас работаю? над генератором тебличек без макросов?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[6]: [proof-of-concept] compile time query language
От: Evgeny.Panasyuk Россия  
Дата: 11.07.16 19:43
Оценка:
Здравствуйте, niXman, Вы писали:

X>без макросов? это ты о том, над чем я сейчас работаю? над генератором тебличек без макросов?


Да, генератор табличек без макросов. Дело в том что для удобного синтаксиса проекций и т.п. желательно иметь код подобный следующему для каждого поля:
struct field_number
{
    struct name_string
    {
        static constexpr auto value() { return "number"; }
    };
    template <typename T>
    struct field
    {
        T number;
    };
    template <typename T>
    static auto &access(T &x)
    {
        return x.number;
    }
};

* name_string — для текста запроса
* field — для синтезирования типа результата с нужными полями
* access — для доступа к нужному полю
Re: [proof-of-concept] compile time query language
От: VTT http://vtt.to
Дата: 11.07.16 19:45
Оценка:
Как я понимаю, основной профит в автоматической генерации строчки SQL запроса?

Или в избавлении от
    auto count = db.read_count();
    xs.reserve(count);

    for(unsigned i=0; i!=count; ++i, db.move_to_next())
    {
        row.value = db.get<double>(0);
        row.id = db.get<int>(1);
        row.number = db.get<int>(2);

        xs.push_back(row);
    }

?

Глядя на название, я сначала подумал, что это compile-time база данных, генерирующая код для выполнения SQL запросов.
Такой вариант наверное был бы поинтереснее.
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Re[7]: [proof-of-concept] compile time query language
От: niXman Ниоткуда https://github.com/niXman
Дата: 11.07.16 19:49
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Да, генератор табличек без макросов.


UDL и вариадик шаблон для строки.
сейчас это выглядит так:
using table = table_t<
   field_t<"id"_S, int>
  ,field_t<"name"_S, std::string>
>;
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: [proof-of-concept] compile time query language
От: niXman Ниоткуда https://github.com/niXman
Дата: 11.07.16 19:52
Оценка:
Здравствуйте, VTT, Вы писали:

VTT>Глядя на название, я сначала подумал, что это compile-time база данных, генерирующая код для выполнения SQL запросов.


а данные она "получает" тоже в компайл-тайм?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: [proof-of-concept] compile time query language
От: Evgeny.Panasyuk Россия  
Дата: 11.07.16 19:55
Оценка: 2 (1)
Здравствуйте, VTT, Вы писали:

VTT>Как я понимаю, основной профит в автоматической генерации строчки SQL запроса?

VTT>Или в избавлении от
VTT>
VTT>

VTT>?

И в том, и в другом. То есть было:
auto handwritten()
{
    using namespace CTQL;

    struct Row
    {
        double value;
        int id;
        int number;
    } row;
    vector_noinline<Row> xs;
    
    dummy_db db;

    db.execute("SELECT foo.value, foo.id, foo.number FROM foo WHERE foo.id>42");

    auto count = db.read_count();
    xs.reserve(count);

    for(unsigned i=0; i!=count; ++i, db.move_to_next())
    {
        row.value = db.get<double>(0);
        row.id = db.get<int>(1);
        row.number = db.get<int>(2);

        xs.push_back(row);
    }
    
    return xs;
}
Стало:
to_vector( from(foo).where(foo.id > 42_i).select(foo.value, foo.id, foo.number) )
При этом ассемблерный код не изменился.

Плюс возможности по декомпозиции:
* итоговый запрос может собираться в разных частях программы
* повторяемые куски разных запросов могут быть вынесены и многократно переиспользованны.

Плюс оптимизация запросов (последний пример исходного сообщения). Плюс поддержка особенностей разных СУБД, и целевых оптимизаций под них.

Плюс, конечно же, типизация.
Отредактировано 11.07.2016 20:21 Evgeny.Panasyuk . Предыдущая версия .
Re[8]: [proof-of-concept] compile time query language
От: Evgeny.Panasyuk Россия  
Дата: 11.07.16 19:57
Оценка:
Здравствуйте, niXman, Вы писали:

EP>>Да, генератор табличек без макросов.

X>UDL и вариадик шаблон для строки.
X>сейчас это выглядит так:
X>
X>using table = table_t<
X>   field_t<"id"_S, int>
X>  ,field_t<"name"_S, std::string>
>>;
X>


Основной вопрос скорее не про строки, а про имена полей в программе. Или ты предлагаешь к полям в проекции по строковым именам обращаться?
Re[9]: [proof-of-concept] compile time query language
От: niXman Ниоткуда https://github.com/niXman
Дата: 11.07.16 19:59
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Или ты предлагаешь к полям в проекции по строковым именам обращаться?

да. ничего лучше(без кодогенерации) я придумать не смог %)

т.е. предполагалось, что юзер будет сначала определять колонки, а потом использовать определения многократно.
типа:
using id = field_t<"id"_S, int>;
using name = field_t<"name"_S, std::string>;
using age = field_t<"age"_S, int>;

using table = table_t<"table_name"_S, id, name, age>;

...

from(foo).where(id > 42).select(name, age);
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Отредактировано 11.07.2016 20:06 niXman . Предыдущая версия . Еще …
Отредактировано 11.07.2016 20:03 niXman . Предыдущая версия .
Re[3]: [proof-of-concept] compile time query language
От: VTT http://vtt.to
Дата: 11.07.16 20:08
Оценка:
Здравствуйте, niXman, Вы писали:

X>Здравствуйте, VTT, Вы писали:


VTT>>Глядя на название, я сначала подумал, что это compile-time база данных, генерирующая код для выполнения SQL запросов.


X>а данные она "получает" тоже в компайл-тайм?


Нет конечно, в компайл-тайм только генерируется код метода, собирающего данные.
т.е. в рантайм нет никаких SQL строчек, а просто вызывается метод, выполняющий заданный в компайл-тайм запрос со всеми оптимизациями.
Я, видите ли, некоторое время назад на фрилансе делал один проектик, где приходилось извлекать / проверять много разных выборок из данных с учетом кучи правил.
Там это сделал, задавая операции при выборке и правила валидации в декларативном виде, как последовательностей из соотв. энумераторов.
На выходе получался шитый код с проверенными на совместимость правилами и запросами.
Были мысли расширить это до чего-то более универсального.
С новыми стандартами сейчас можно было бы прямо в compile-time парсить строчки запросов и прочее.
Еще я про это вспомнил из-за соседнего топика
Автор: kochetkov.vladimir
Дата: 08.07.16
.
По идее, компоновка SQL-запросов во время компиляции позволила бы устранить целый класс атак типа SQL injection за счет отсутствия интерпретатора SQL в рантайм.
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Отредактировано 11.07.2016 20:16 VTT . Предыдущая версия . Еще …
Отредактировано 11.07.2016 20:15 VTT . Предыдущая версия .
Re[10]: [proof-of-concept] compile time query language
От: Evgeny.Panasyuk Россия  
Дата: 11.07.16 20:09
Оценка:
Здравствуйте, niXman, Вы писали:

EP>>Или ты предлагаешь к полям в проекции по строковым именам обращаться?

X>да. ничего лучше(без кодогенерации) я придумать не смог %)

Это поможет решить следующая фича:
template<char...>
struct reification;

Где компилятор автоматически бы создавал специализации следующего вида при обращении к ним:
template<>
struct reification<'n', 'u', 'm', 'b', 'e', 'r'>
{
    template <typename T>
    struct field
    {
        T number;
    };
    template <typename T>
    static auto &access(T &x)
    {
        return x.number;
    }
    // ... number function, number type, etc, etc
};

Думаю стоит подумать над proposal'ом.

Сейчас кстати это можно сэмулировать следующим образом. Даём пользователю
template<char...>
struct reification;

Когда он обращается к специализации reification<'n', 'u', 'm', 'b', 'e', 'r'>, получаем ошибку компиляции вида
main.cpp:7:47: error: implicit instantiation of undefined template 'reification<'n', 'u', 'm', 'b', 'e', 'r'>'

    reification<'n', 'u', 'm', 'b', 'e', 'r'> x;

Парсим ошибки компиляции простым скриптом и генерируем специализации в специальный .hpp файл. При повторной компиляции ошибок уже не будет.
Re[10]: [proof-of-concept] compile time query language
От: Evgeny.Panasyuk Россия  
Дата: 11.07.16 20:11
Оценка:
Здравствуйте, niXman, Вы писали:

X>т.е. предполагалось, что юзер будет сначала определять колонки, а потом использовать определения многократно.

X>типа:
X>
X>using id = field_t<"id"_S, int>;
X>using name = field_t<"name"_S, std::string>;
X>using age = field_t<"age"_S, int>;

X>using table = table_t<"table_name"_S, id, name, age>;

X>...

X>from(foo).where(id > 42).select(name, age);
X>


Этого недостаточно для того чтобы к результирующей строке можно было обратиться через точку, то есть вот так:
for(auto &&row : db(from(foo).where(id > 42).select(name, age)))
    cout << row.name;

не получится.
Re[11]: [proof-of-concept] compile time query language
От: niXman Ниоткуда https://github.com/niXman
Дата: 11.07.16 20:16
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Этого недостаточно для того чтобы к результирующей строке можно было обратиться через точку, то есть вот так:

EP>
EP>for(auto &&row : db(from(foo).where(id > 42).select(name, age)))
EP>    cout << row.name;
EP>

EP>не получится.

та понятно =)
ща я тот код откопаю и гляну, как оно там планировалось...
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.