Re[137]: Тормознутость и кривость linq
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 02.07.16 18:53
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

G>>Мы уже посмотрели твой sqlpp11. Он не умеет генерить разный sql для разных баз.


EP>В каком смысле не умеет? Пиши свой коннектор, и генерируй какой угодно запрос. Там например есть пример коннектора к обычным контейнерам.


Возможность скорее гипотетическая. трансляция sql-sql значит, что на ровном месте сложность решения много выше чем в linq. То есть, никто не станет дурить себе мозг.
Re[131]: Тормознутость и кривость linq
От: IT Россия linq2db.com
Дата: 02.07.16 19:27
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Но я здесь уже демонстрировал, что переход к динамике (т.е. формирования строки запроса в рантайме, в зависимости от каких-то внешних условий) добавляет незначительные временные затраты (в моём тесте речь шла о паре микросекунд), несравнимые с накладными расходами от использования того же linq.


Это практические результаты или теория?
Если нам не помогут, то мы тоже никого не пощадим.
Re[133]: Тормознутость и кривость linq
От: IT Россия linq2db.com
Дата: 02.07.16 19:41
Оценка: +1
Здравствуйте, alex_public, Вы писали:

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


_>Склейка строк для реализации динамического запроса может выглядеть так (целиком работающий код можешь глянуть http://rsdn.ru/forum/flame.comp/6433119.1):
Автор: alex_public
Дата: 01.05.16

_>
_>if(...) q.where.add(test.fvalue>i);
_>


Боюсь ты плохо представляешь себе динамику. На деле происходит следующее:

if (...) q = q.Where(t => t.ParentTable.Field1 == 10);


ParentTable — это ассоциация, при возникновении которой в запрос нужно срочно добавлять JOIN к ParentTable. Т.е. склейка просто не будет работать. Клеить нужно SQL AST, а уже по нему далее строить SQL.

Есть варианты попроще. Например, вот типичный сценарий для веб приложения:

q = ...Select(t => new { t.Field1, t.Field2 });

var count = q.Count();
var page  = q.Skip(n).Take(m);


Т.е. подготавливается базовый запрос, на базе которого потом запрашивается общее количество записей, а потом выбирается одна страница для показа. Где тут может быть склейка?
Если нам не помогут, то мы тоже никого не пощадим.
Re[123]: Тормознутость и кривость linq
От: IT Россия linq2db.com
Дата: 02.07.16 20:02
Оценка: +1
Здравствуйте, alex_public, Вы писали:

_>О, я смотрю это уже становится похоже на реальность (уже 16% накладных расходов),


Что сделать что-то похожее на реальность нужно сюда прикрутить, например, весь веб стек. Тогда это будет похоже на реальность.

_>причём на достаточно долгих запросах.


Это не долгие запросы. Их просто много. Вот долгие запросы (по максимуму, по 830 записей):

LINQ: 8300000 in 00:00:30.5171917
ADO:  8300000 in 00:00:30.3152047
SQL:  8300000 in 00:00:30.2134637


_>Теперь если ещё сделать быстрые запросы (например сделав тест с СУБД на том же компьютере), то скорее всего получим в точности результаты liiw (с 90% накладных расходов). Я уже молчу что будет в случае весьма распространённого в вебе запроса одиночной строки по индексу (например пользователя по id сессии)...


Ещё раз. Все твои пресловутые 90% утонут в веб-стеке

_>Так кто там говорил о предельном максимуме расходов в 5%? )


Ну смотри на результат выше для длинных запросов. Десятые процента
Если нам не помогут, то мы тоже никого не пощадим.
Re[129]: Тормознутость и кривость linq
От: IT Россия linq2db.com
Дата: 02.07.16 20:05
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Гитхаб не репрезентативен, потому что на него не принято выкладываться целым областям индустрии. Кто-нибудь видел там выложенные исходники прошивок микроконтроллеров автомобиля, выкладываемого автоконцернами? Или прошивок для ЧПУ (не домашних поделок, а настоящих) и прочей промышленной автоматизации? )


Можно подумать TIOBI видел много прошивок и энтерпрайз приложений.
Если нам не помогут, то мы тоже никого не пощадим.
Re[135]: Тормознутость и кривость linq
От: Ночной Смотрящий Россия  
Дата: 02.07.16 22:30
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

НС>>Нет. Это разные слои приложения как минимум.

EP>И что из того что слои?

Тяжко. То, что эти слои почти всегда — независимые единицы компиляции.

НС>>Про фильтрацию и выюор колонок тебе IT уже написал и ты согласился что это динамика.

EP>Он конкретно сказал про грид с 50-ю опциональными колонками и т.п.

Так это тоже самое. Пользователь задает условия фильтрации гридов, эти условия нужно накладывать на запросы в бизнес-коде. Совершенно типовая для ERP задачка.

EP>Ты же говоришь про "достраиваются платформой" — то есть мол запрос размазан по разным частям приложения — это может быть как статикой, так и динамикой,


Нет, это не может быть статикой, потому что зависит от действий пользователя.

EP>Я думаю что многоразовых платформ намного меньше чем конечных приложений, причём не важно что там — ERP или что-либо другое.


А если в количестве запросов считать?
Re[142]: Тормознутость и кривость linq
От: Evgeny.Panasyuk Россия  
Дата: 03.07.16 00:38
Оценка:
Здравствуйте, gandjustas, Вы писали:

EP>>>>Показывающий что конкретно? Проекции? Фильтры? Автоматические join'ы по связям?

G>>>Фильтры и проекции, с джоинами потом разберемся
EP>>То есть после примера с фильтрами и проекциями ты скажешь что мол нет джоинов, того и того, поэтому нещитово и вообще "невозможно"
G>Сделай хотя бы простой вариант.

И что это изменит?

EP>>>>Это всё ни одна сотня строк кода, реализовать которые мне не интересно.

G>>>Тогда какой смысл в том, что ты пишешь?
EP>>Что значит какой? Я утверждаю что это вполне реализуемо, то есть все технические возможности в наличии.
EP>>Некоторые же из собравшихся считают что нет, мол проекции не реализуются, статическая декомпозиция "никому не удавалась" — я в ответ показываю конкретные компилируемые примеры.
G>Ты сейчас апеллируешь к теоретической возможности применить подходы X, Y, Z,... , чтобы получит статическую генерацию.
G>Хотя никто, в том числе ты, даже X и Y вместе не применял, и не факт, что это вообще получится сделать.

Я X и Y вместе применял, только в другом, интересном мне контексте. Вот например
Автор: Evgeny.Panasyuk
Дата: 12.10.14
compile-time обработка DSL в строке, генерация новых строк + мэппинг, сравнение результирующего ASM с оптимальным ручным вариантом.
На этом форуме я приводил много примеров, в том числе на смежные темы, причём полностью компилируемые и с LIVE DEMO — то есть в один клик можно с этим кодом поиграться, ничего не настраивая.
И если я говорю что что-то вполне реализуемо, значит я вижу все необходимые компоненты для реализации И всё необходимое для их взаимодействия — и слов на ветер не бросаю.

G>>>На практике никто такое не сделал, значит невозможно.

EP>> Нет, не значит, очевидно же.
G>Очевидно, что нет доказательств, что возможно, только предположение.

Это с твоей стороны предположение, а я знаю все технические аспекты, поэтому и могут утверждать.

G>Я склонен верить в то, что если что-то не случается на практике, то это невозможно, даже если теоретически может быть.


А какой смысл такой веры? Постоянно случается то, чего раньше не было. Закладывая же предположение о том, что это всё это невозможно в основу своего поведения, ты сам отсекаешь себе множество вариантов развития

G>>>Иначе уже была бы реализован аналог linq на C++.

EP>>Альтернативы есть, пусть и не 1-в-1 аналогичные по замыслу, но тем не менее. Тот же sqlpp11.
G>Я посмотрел sqlpp11, это даже близко не linq. В нем тупо нет средств комползиции.

В каком смысле нет средств композиции?

G>Это api для более-менее типизированного построения примитивных запросов. Он не может никаким образом получить два разных запроса из одного и того же куска кода. Даже теоретически.


Это ещё почему? Например у него есть коннектор в БД, и к обычным контейнерам — один и тот же запрос может выполнять совершенно разные веши

G>>>Меня смущает, что ты каждый раз даешь пример одного аспекта, а не все вместе.

EP>>Потому что это требует меньше времени на реализацию, и является ответом на конкретное сомнение, например как в случае с проекциями.
G>Я понимаю почему ты так пишешь,

И почему же?

G>я также понимаю, что нет гарантии, что можно два твоих примера объединить в один рабочий.


С твоей стороны ты не видишь гарантии, потому что не знаешь необходимые технические аспекты C++. Но тут даже речь не про C++, а вообще про сам подход статической генерации запросов из EDSL, и вот тут ты уже должен понимать что это вполне возможно.

G>>>Похоже что все вместе не взлетит от слова вообще.

EP>>EDSL'ей для C++ много разных, в том числе и на тему SQL, метапрограммирование полное по Тьюрингу, есть compile-time обработка и генерация строк — то есть всё необходимое.
G>А linq даже близко нет. Странно, да?

Ничего странного — нет глобальной потребности, соответственно нет проработанных решений.

G>>>>>Кроме того сразу видна проблема. У тебя слишком коноетный тип

EP>>>>Это плата за статику.
G>>>И как будешь разруливать?
EP>>Разруливать что именно?
G>То что типы у тебя слшиком конкретные, а комбинаторы наоборот должны работать с наиболее общими типами.

То что у нас во время компиляции конкретные типы, не означает что с ними нельзя работать обобщённо. Обобщённое программирование вообще-то одна из сильных сторон C++.

G>where должен применяться и к from, и к select и к еще куче всяких других типов.


И пусть применяется, в чём проблема-то?

EP>>>>Пример на эту тему я уже показал выше
Автор: Evgeny.Panasyuk
Дата: 01.07.16
.

G>>>Ты предлагаешь писать свой where к каждому типу?
G>>>Это неживая идея изначально.
EP>>В каком смысле "к каждому"?
G>У тебя where находится в структуре Foo,

Да причём тут вообще это? Ты просил пример декомпозиции, а именно вынесение .where(...) в отдельную сущность — я его показал, теперь ты придираешься к тому что у меня есть сущность с where

G>в реальности у тебя вместо Foo будут from, where,select,groupby и набор таких типов может расширяться. При текущей реализации придется where выписывать в каждом типе.


Пример был вообще на другую тему
Re[135]: Тормознутость и кривость linq
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 05.07.16 07:20
Оценка: +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

G>>2) Как делать декомпозицию \ композицию таких запросов? В идеале так:http://blog.gandjustas.ru/2010/05/30/iqueryable-generics/


EP>В статье описана борьба с неким ограничением LINQ.


Не ограничение, а одна из основных возможностей ради которых все и начиналось. В sqlpp аналогичный фокус используется для того, что бы работать против stl-контейнеров.

EP>На C++ нет проблемы вынести выделенную часть из выражения

EP>
EP>something.Where(o => o.Visible)
EP>
в отдельную сущность и прилепить её к чему угодно. Пример:


Ты показал не тот пример Ты показал лямбду, когда тебя просили Expression. Лямбда выполняется в твоем процессе. Экспрешн — ты вообще не в курсе, где это выполняется, выполняется ли и как выполняется.

G>>3) Как ты реализуешь такой сценарий:

G>>
G>>IQueryable<X> F(IQueryable<X> xs, IEnumerable<int> m)
G>>{
G>>    return xs.Where(x => m.Contains(x.y));
G>>}
G>>

G>>Такой запрос преобразуется в
G>>
G>>...
G>>where x.y in (@p1, @p2,...) -- количество значений в in будет зависеть от исходного массива
G>>

G>>?

EP>Структура запроса не меняется, поэтому достаточно сгенерировать в runtime только вот эту часть @p1, @p2,...


Меняется структура того запроса, который вызовет эту функцию. Может и не быть никакого @p1, @p2 а будет какой нибудь джойн, а может и вовсе оба сложных запроса выродятся в какой нибудь примитивнейший частный случай.
Re[122]: Тормознутость и кривость linq
От: artelk  
Дата: 05.07.16 08:24
Оценка:
Здравствуйте, IT, Вы писали:

IT>Добавил, начало скакать туда сюда, пришлось увеличить количество итераций и нивелировать порядок выполнения. Получилось так:


IT>
IT>LINQ: 1000000 in 00:00:56.0547832
IT>ADO:  1000000 in 00:00:49.1683344
IT>SQL:  1000000 in 00:00:48.4624714
IT>


Я правильно подозреваю, в тесте все данные лежали в кэше на субд сервере? В реальности будут чтения с дисков, так что подобные сравнения — это замеры у кого ноль длиннее.
Re[123]: Тормознутость и кривость linq
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 05.07.16 08:36
Оценка:
Здравствуйте, artelk, Вы писали:

IT>>Добавил, начало скакать туда сюда, пришлось увеличить количество итераций и нивелировать порядок выполнения. Получилось так:


IT>>
IT>>LINQ: 1000000 in 00:00:56.0547832
IT>>ADO:  1000000 in 00:00:49.1683344
IT>>SQL:  1000000 in 00:00:48.4624714
IT>>


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


Так в том то и дело, что это жесточайшая синтетика. Но вот alex_publiс уверен, что это фатальный недостаток linq2db и других OR/M на базе linq.
Re[136]: Тормознутость и кривость linq
От: Evgeny.Panasyuk Россия  
Дата: 05.07.16 09:24
Оценка:
Здравствуйте, Ikemefula, Вы писали:

G>>>3) Как ты реализуешь такой сценарий:

G>>>
G>>>IQueryable<X> F(IQueryable<X> xs, IEnumerable<int> m)
G>>>{
G>>>    return xs.Where(x => m.Contains(x.y));
G>>>}
G>>>

G>>>Такой запрос преобразуется в
G>>>
G>>>...
G>>>where x.y in (@p1, @p2,...) -- количество значений в in будет зависеть от исходного массива
G>>>

G>>>?
EP>>Структура запроса не меняется, поэтому достаточно сгенерировать в runtime только вот эту часть @p1, @p2,...
I>Меняется структура того запроса, который вызовет эту функцию. Может и не быть никакого @p1, @p2 а будет какой нибудь джойн,

Здесь речь конкретно про Contains.

I>а может и вовсе оба сложных запроса выродятся в какой нибудь примитивнейший частный случай.


Так и в случае с compile-time EDSL такое возможно
Re[137]: Тормознутость и кривость linq
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 05.07.16 09:37
Оценка: +2
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>>>Структура запроса не меняется, поэтому достаточно сгенерировать в runtime только вот эту часть @p1, @p2,...

I>>Меняется структура того запроса, который вызовет эту функцию. Может и не быть никакого @p1, @p2 а будет какой нибудь джойн,

EP>Здесь речь конкретно про Contains.


Именно ! Из за него и будут джойны, ибо типичный пров в курсе, что такое Contains и интерпретирует его по своему усмотрению.

I>>а может и вовсе оба сложных запроса выродятся в какой нибудь примитивнейший частный случай.


EP>Так и в случае с compile-time EDSL такое возможно


Теоретически возможно, но пока ничего работающего ни ты, ни alex_public не показали.
Re[123]: Тормознутость и кривость linq
От: IT Россия linq2db.com
Дата: 05.07.16 13:10
Оценка:
Здравствуйте, artelk, Вы писали:

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


В реальности ещё будет веб стэк для веб приложений.
Если нам не помогут, то мы тоже никого не пощадим.
Re[136]: Тормознутость и кривость linq
От: Evgeny.Panasyuk Россия  
Дата: 05.07.16 15:27
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>>>Нет. Это разные слои приложения как минимум.

EP>>И что из того что слои?
НС>Тяжко. То, что эти слои почти всегда — независимые единицы компиляции.

А нужны ли независимые TU? Почти всегда нужно логическое разделение на файлы, а не на TU. Техники типа Unity Builds прекрасно работают даже для больших проектов.

EP>>Я думаю что многоразовых платформ намного меньше чем конечных приложений, причём не важно что там — ERP или что-либо другое.

НС>А если в количестве запросов считать?

Выполненных или написанных? Запросов платформ ERP от всех ERP-запросов, или вообще от всех запросов во всех областях?
Re[137]: Тормознутость и кривость linq
От: Ночной Смотрящий Россия  
Дата: 05.07.16 16:55
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

НС>>Тяжко. То, что эти слои почти всегда — независимые единицы компиляции.

EP>А нужны ли независимые TU?

Нужны. Потому что они даже у одного поставщика почти всегда имеют независимый релизный цикл. А чаще встречается ситуация, когда платформу поставляет один вендор, базовое прикладное решение второй, а конкретное внедрение — третий.

EP> Почти всегда нужно логическое разделение на файлы, а не на TU.


Очень далек ты от мира ERP.

EP>>>Я думаю что многоразовых платформ намного меньше чем конечных приложений, причём не важно что там — ERP или что-либо другое.

НС>>А если в количестве запросов считать?
EP>Выполненных или написанных?

Написанных, разумеется.

EP> Запросов платформ ERP от всех ERP-запросов, или вообще от всех запросов во всех областях?


Второе.
Re[142]: Тормознутость и кривость linq. Compile-time EDSL DB query proof-of-conc
От: Evgeny.Panasyuk Россия  
Дата: 05.07.16 23:58
Оценка: :))
Здравствуйте, gandjustas, Вы писали:

G>>>>>Потому что построить дерево на шаблонах несложно. Самое интересное начинается дальше.

EP>>>>Что именно тебя смущает? Говори конкретный аспект и я расскажу (и возможно покажу) каким образом он реализуется
G>>>Меня смущает, что ты каждый раз даешь пример одного аспекта, а не все вместе.
EP>>Потому что это требует меньше времени на реализацию, и является ответом на конкретное сомнение, например как в случае с проекциями.
G>Я понимаю почему ты так пишешь

И почему же?

EP>>>>Показывающий что конкретно? Проекции? Фильтры? Автоматические join'ы по связям?

G>>>Фильтры и проекции, с джоинами потом разберемся
EP>>То есть после примера с фильтрами и проекциями ты скажешь что мол нет джоинов, того и того, поэтому нещитово и вообще "невозможно"
G>Сделай хотя бы простой вариант.


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

#include "ctql.hpp"

#include <iostream>

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

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

Вывод:

execute select foo.value, foo.id, foo.number from foo where 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 
get<double> 0 
get<int> 1 
get<int> 2 
move_to_next 
get<double> 0 
get<int> 1 
get<int> 2 
move_to_next 
100 1 200
110 1.01 210
120 1.02 220
130 1.03 230
140 1.04 240

Live Demo


Сравнение с ручной версией

#include "ctql.hpp"

#include <iostream>

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

NOINLINE auto handwritten()
{
    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 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)
{
    for(auto &x : xs)
        std::cout << x.id << " " << x.value << " " << x.number << std::endl;
}

int main()
{
    print( from(foo).where(foo.id > 42_i).select(foo.value, foo.id, foo.number).to_vector() );
    print_line();
    print( handwritten() );
}

Вывод:

execute select foo.value, foo.id, foo.number from foo where 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 
get<double> 0 
get<int> 1 
get<int> 2 
move_to_next 
get<double> 0 
get<int> 1 
get<int> 2 
move_to_next 
100 1 200
110 1.01 210
120 1.02 220
130 1.03 230
140 1.04 240

execute select foo.value, foo.id, foo.number from foo where 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 
get<double> 0 
get<int> 1 
get<int> 2 
move_to_next 
get<double> 0 
get<int> 1 
get<int> 2 
move_to_next 
100 1 200
110 1.01 210
120 1.02 220
130 1.03 230
140 1.04 240

Benchmark

Никакой benchmark не нужен, так как результрующий ассемблерный код в обоих вариантах идентичен, с точностью до идентификаторов — то есть истинный zero overhead
g++ ctql.cpp -std=c++14 -O3 -Wall -pedantic -DNDEBUG -S -masm=intel &&
cat ctql.s | c++filt > ctql.filtered.s &&

sed -n '/.*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-06 02:54:41.734542800 +0300
+++ to_vector.s 2016-07-06 02:54:41.695540600 +0300
@@ -1,5 +1,5 @@
-handwritten():
-.LFB1999:
+projected<make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, string<(char)105, (char)100, (char)62, (char)52, (char)50>, table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >::to_vector():
+.LFB2019:
    push    r12
    .seh_pushreg    r12
    push    rbp
@@ -15,23 +15,23 @@
    .seh_endprologue
    lea rbx, 32[rsp]
    mov rdi, rcx
-   call    vector_noinline<handwritten()::Row>::vector_noinline()
-   lea rdx, .LC9[rip]
+   call    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline()
+   lea rdx, string_value<(char)115, (char)101, (char)108, (char)101, (char)99, (char)116, (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)102, (char)114, (char)111, (char)109, (char)32, (char)102, (char)111, (char)111, (char)32, (char)119, (char)104, (char)101, (char)114, (char)101, (char)32, (char)105, (char)100, (char)62, (char)52, (char)50>::value[rip]
    mov rcx, rbx
    mov DWORD PTR 32[rsp], 0
-.LEHB0:
+.LEHB2:
    call    dummy_db::execute(char const*)
    call    dummy_db::read_count() const [clone .isra.27]
    mov edx, eax
    mov rcx, rdi
    mov rbp, rdx
-   call    vector_noinline<handwritten()::Row>::reserve(unsigned long) [clone .constprop.29]
+   call    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, 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 dummy_db::get<double>(unsigned int) const [clone .constprop.35]
    mov rcx, rbx
@@ -43,14 +43,14 @@
    mov rdx, r12
    mov rcx, rdi
    mov DWORD PTR 60[rsp], eax
-   call    vector_noinline<handwritten()::Row>::push_back(handwritten()::Row const&) [clone .constprop.31]
+   call    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    mov rcx, rbx
    add esi, 1
    call    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    vector_noinline<handwritten()::Row>::~vector_noinline()
+   call    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, 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
-.LLSDA1999:
+.LLSDA2019:
    .byte   0xff
    .byte   0xff
    .byte   0x1
-   .uleb128 .LLSDACSE1999-.LLSDACSB1999
-.LLSDACSB1999:
-   .uleb128 .LEHB0-.LFB1999
-   .uleb128 .LEHE0-.LEHB0
-   .uleb128 .L106-.LFB1999
+   .uleb128 .LLSDACSE2019-.LLSDACSB2019
+.LLSDACSB2019:
+   .uleb128 .LEHB2-.LFB2019
+   .uleb128 .LEHE2-.LEHB2
+   .uleb128 .L175-.LFB2019
    .uleb128 0
-   .uleb128 .LEHB1-.LFB1999
-   .uleb128 .LEHE1-.LEHB1
+   .uleb128 .LEHB3-.LFB2019
+   .uleb128 .LEHE3-.LEHB3
    .uleb128 0
    .uleb128 0
-.LLSDACSE1999:
-   .text
+.LLSDACSE2019:
+   .section    .text$_ZN9projectedI10make_tableIN7foo_aux11name_stringEJNS1_9id_columnENS1_11code_columnENS1_12value_columnENS1_13number_columnEEE6stringIJLc105ELc100ELc62ELc52ELc50EEEJ12table_columnIS1_dNS5_11field_valueEESA_IS1_iNS3_8field_idEESA_IS1_iNS6_12field_numberEEEE9to_vectorEv,"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 <iostream>
#include <iterator>
#include <cassert>
#include <utility>
#include <vector>
#include <tuple>

/******************************************************************************/
#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 5;
    }
    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
{
    using value_type = string_value<cs...>;
};

template<typename, typename> struct make_string_aux;

template<typename String, std::size_t ...Is>
struct make_string_aux<String, std::index_sequence<Is...>>
{
    using type = string<String::value()[Is]...>;
};

template<typename String, std::size_t length = c_str_length(String::value())>
using make_string = typename make_string_aux
<
        String, std::make_index_sequence<length>
>::type;

using space = string<' '>;
using comma = string<','>;
using dot = string<'.'>;

/******************************************************************************/
template<typename...> struct concat_aux;

template<typename ...Strings>
using concat = typename concat_aux<Strings...>::type;

template<typename S1>
struct concat_aux<S1>
{
    using type = S1;
};

template<char ...cs1, char ...cs2>
struct concat_aux<string<cs1...>, string<cs2...>>
{
    using type = string<cs1..., cs2...>; 
};

template<typename S1, typename S2, typename ...Rest>
struct concat_aux<S1, S2, Rest...>
{
    using type = concat<concat<S1, S2>, Rest...>;
};

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

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

#define WRAP_STRING(name, str)                                             \
    struct name ## _aux { static constexpr auto value() { return str; } }; \
    using name = make_string<name ## _aux>                                 \
/**/

template<typename Field>
using name_string = make_string<typename Field::name_string>;

/******************************************************************************/
#define FIELD(name)                                                 \
    struct BOOST_PP_CAT(field_, name)                               \
    {                                                               \
        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 Table, typename T, typename Field>
struct table_column
{
    using table = Table;
    using column_type = T;
    using field = Field;

    template<char ...cs>
    auto operator>(string<cs...>) const
    {
        return concat<name_string<field>, string<'>', cs...>>{};
    }
};

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>...
{};

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

template<typename Column>
using full_column_name = concat
<
    name_string<typename Column::table>,
    dot,
    name_string<typename Column::field>
>;

template<typename Table, typename Condition, typename FirstColumn, typename ...Rest>
struct make_sql
{
    WRAP_STRING(select, "select");
    WRAP_STRING(from, "from");
    WRAP_STRING(where, "where");

    using columns = concat
    <
        full_column_name<FirstColumn>,
        concat<comma, space, full_column_name<Rest>>...
    >;

    using type = concat
    <
        select, space, columns, space,
        from, space, name_string<Table>, space,
        where, space, Condition
    >;
};

/******************************************************************************/
// 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 projected
{
    NOINLINE static auto to_vector()
    {
        using sql_text = make_sql<Table, Condition, Columns...>;

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

        vector_noinline<Row> xs;

        dummy_db db;
        db.execute(sql_text::type::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;
    }
};

template<typename Table, typename Condition>
struct filtered
{
    template<typename ...Columns>
    auto select(Columns...)
    {
        return projected<Table, Condition, Columns...>{};
    }
};

template<typename Table>
struct from_aux
{
    template<typename Condition>
    auto where(Condition)
    {
        return filtered<Table, Condition>{};
    }
};

template<typename Table>
auto from(Table)
{
    return from_aux<Table>{};
}

/******************************************************************************/
// 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 = 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)                                    \
        STRUCT_WRAP_STRING(name_string, #name);                               \
        using type = make_table<name_string FOR_EACH_DECL(COLUMN_NAME, seq)>; \
    };                                                                        \
    name ## _aux :: type name                                                 \
/**/

#endif

  ctql.cpp
#include "ctql.hpp"

#include <iostream>

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

NOINLINE auto handwritten()
{
    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 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)
{
    for(auto &x : xs)
        std::cout << x.id << " " << x.value << " " << x.number << std::endl;
}

int main()
{
    print( from(foo).where(foo.id > 42_i).select(foo.value, foo.id, foo.number).to_vector() );
    print_line();
    print( handwritten() );
}

  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    vector_noinline<handwritten()::Row>::vector_noinline(); .scl    3;  .type   32; .endef
    .seh_proc   vector_noinline<handwritten()::Row>::vector_noinline()
vector_noinline<handwritten()::Row>::vector_noinline():
.LFB2001:
    .seh_endprologue
    mov QWORD PTR [rcx], 0
    mov QWORD PTR 8[rcx], 0
    mov QWORD PTR 16[rcx], 0
    ret
    .seh_endproc
    .def    vector_noinline<handwritten()::Row>::vector_noinline(); .scl    3;  .type   32; .endef
    .set    vector_noinline<handwritten()::Row>::vector_noinline(),vector_noinline<handwritten()::Row>::vector_noinline()
    .align 2
    .p2align 4,,15
    .def    vector_noinline<handwritten()::Row>::~vector_noinline();    .scl    3;  .type   32; .endef
    .seh_proc   vector_noinline<handwritten()::Row>::~vector_noinline()
vector_noinline<handwritten()::Row>::~vector_noinline():
.LFB2004:
    .seh_endprologue
    mov rcx, QWORD PTR [rcx]
    test    rcx, rcx
    je  .L3
    jmp operator delete(void*)
.L3:
    ret
    .seh_endproc
    .def    vector_noinline<handwritten()::Row>::~vector_noinline();    .scl    3;  .type   32; .endef
    .set    vector_noinline<handwritten()::Row>::~vector_noinline(),vector_noinline<handwritten()::Row>::~vector_noinline()
    .align 2
    .p2align 4,,15
    .def    vector_noinline<handwritten()::Row>::push_back(handwritten()::Row const&) [clone .constprop.31];    .scl    3;  .type   32; .endef
    .seh_proc   vector_noinline<handwritten()::Row>::push_back(handwritten()::Row const&) [clone .constprop.31]
vector_noinline<handwritten()::Row>::push_back(handwritten()::Row const&) [clone .constprop.31]:
.LFB2600:
    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    vector_noinline<handwritten()::Row>::reserve(unsigned long) [clone .constprop.29];  .scl    3;  .type   32; .endef
    .seh_proc   vector_noinline<handwritten()::Row>::reserve(unsigned long) [clone .constprop.29]
vector_noinline<handwritten()::Row>::reserve(unsigned long) [clone .constprop.29]:
.LFB2602:
    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    dummy_db::read_count() const [clone .isra.27];  .scl    3;  .type   32; .endef
    .seh_proc   dummy_db::read_count() const [clone .isra.27]
dummy_db::read_count() const [clone .isra.27]:
.LFB2588:
    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, 5
    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 dummy_db::get<double>(unsigned int) const [clone .constprop.35]; .scl    3;  .type   32; .endef
    .seh_proc   double dummy_db::get<double>(unsigned int) const [clone .constprop.35]
double dummy_db::get<double>(unsigned int) const [clone .constprop.35]:
.LFB2596:
    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 dummy_db::get<int>(unsigned int) const [clone .constprop.37];   .scl    3;  .type   32; .endef
    .seh_proc   int dummy_db::get<int>(unsigned int) const [clone .constprop.37]
int dummy_db::get<int>(unsigned int) const [clone .constprop.37]:
.LFB2594:
    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 dummy_db::get<int>(unsigned int) const [clone .constprop.36];   .scl    3;  .type   32; .endef
    .seh_proc   int dummy_db::get<int>(unsigned int) const [clone .constprop.36]
int dummy_db::get<int>(unsigned int) const [clone .constprop.36]:
.LFB2595:
    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$_ZN8dummy_db7executeEPKc,"x"
    .linkonce discard
    .align 2
    .p2align 4,,15
    .globl  dummy_db::execute(char const*)
    .def    dummy_db::execute(char const*); .scl    2;  .type   32; .endef
    .seh_proc   dummy_db::execute(char const*)
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$_ZN8dummy_db12move_to_nextEv,"x"
    .linkonce discard
    .align 2
    .p2align 4,,15
    .globl  dummy_db::move_to_next()
    .def    dummy_db::move_to_next();   .scl    2;  .type   32; .endef
    .seh_proc   dummy_db::move_to_next()
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 dummy_db::get<int>(unsigned int) const
    .def    int dummy_db::get<int>(unsigned int) const; .scl    2;  .type   32; .endef
    .seh_proc   int dummy_db::get<int>(unsigned int) const
int 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 dummy_db::get<double>(unsigned int) const
    .def    double dummy_db::get<double>(unsigned int) const;   .scl    2;  .type   32; .endef
    .seh_proc   double dummy_db::get<double>(unsigned int) const
double 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 id>42\0"
    .text
    .p2align 4,,15
    .globl  handwritten()
    .def    handwritten();  .scl    2;  .type   32; .endef
    .seh_proc   handwritten()
handwritten():
.LFB1999:
    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    vector_noinline<handwritten()::Row>::vector_noinline()
    lea rdx, .LC9[rip]
    mov rcx, rbx
    mov DWORD PTR 32[rsp], 0
.LEHB0:
    call    dummy_db::execute(char const*)
    call    dummy_db::read_count() const [clone .isra.27]
    mov edx, eax
    mov rcx, rdi
    mov rbp, rdx
    call    vector_noinline<handwritten()::Row>::reserve(unsigned long) [clone .constprop.29]
    test    ebp, ebp
    je  .L100
    lea r12, 48[rsp]
    xor esi, esi
    .p2align 4,,10
.L103:
    mov rcx, rbx
    call    double dummy_db::get<double>(unsigned int) const [clone .constprop.35]
    mov rcx, rbx
    movsd   QWORD PTR 48[rsp], xmm0
    call    int dummy_db::get<int>(unsigned int) const [clone .constprop.36]
    mov rcx, rbx
    mov DWORD PTR 56[rsp], eax
    call    int dummy_db::get<int>(unsigned int) const [clone .constprop.37]
    mov rdx, r12
    mov rcx, rdi
    mov DWORD PTR 60[rsp], eax
    call    vector_noinline<handwritten()::Row>::push_back(handwritten()::Row const&) [clone .constprop.31]
    mov rcx, rbx
    add esi, 1
    call    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    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
.LLSDA1999:
    .byte   0xff
    .byte   0xff
    .byte   0x1
    .uleb128 .LLSDACSE1999-.LLSDACSB1999
.LLSDACSB1999:
    .uleb128 .LEHB0-.LFB1999
    .uleb128 .LEHE0-.LEHB0
    .uleb128 .L106-.LFB1999
    .uleb128 0
    .uleb128 .LEHB1-.LFB1999
    .uleb128 .LEHE1-.LEHB1
    .uleb128 0
    .uleb128 0
.LLSDACSE1999:
    .text
    .seh_endproc
    .section    .text$_ZN15vector_noinlineI8make_rowIJ12table_columnI7foo_auxdNS2_12value_column11field_valueEES1_IS2_iNS2_9id_column8field_idEES1_IS2_iNS2_13number_column12field_numberEEEEEC1Ev,"x"
    .linkonce discard
    .align 2
    .p2align 4,,15
    .globl  vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline()
    .def    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline();  .scl    2;  .type   32; .endef
    .seh_proc   vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline()
vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline():
.LFB2022:
    .seh_endprologue
    mov QWORD PTR [rcx], 0
    mov QWORD PTR 8[rcx], 0
    mov QWORD PTR 16[rcx], 0
    ret
    .seh_endproc
    .weak   vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline()
    .def    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline();  .scl    2;  .type   32; .endef
    .set    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline(),vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline()
    .section    .text$_ZN15vector_noinlineI8make_rowIJ12table_columnI7foo_auxdNS2_12value_column11field_valueEES1_IS2_iNS2_9id_column8field_idEES1_IS2_iNS2_13number_column12field_numberEEEEED1Ev,"x"
    .linkonce discard
    .align 2
    .p2align 4,,15
    .globl  vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline()
    .def    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline(); .scl    2;  .type   32; .endef
    .seh_proc   vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline()
vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline():
.LFB2025:
    .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   vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline()
    .def    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline(); .scl    2;  .type   32; .endef
    .set    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline(),vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::~vector_noinline()
    .section    .text$_ZN15vector_noinlineI8make_rowIJ12table_columnI7foo_auxdNS2_12value_column11field_valueEES1_IS2_iNS2_9id_column8field_idEES1_IS2_iNS2_13number_column12field_numberEEEEE7reserveEm,"x"
    .linkonce discard
    .align 2
    .p2align 4,,15
    .globl  vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long)
    .def    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long); .scl    2;  .type   32; .endef
    .seh_proc   vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long)
vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long):
.LFB2170:
    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   vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long)
    .def    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long); .scl    2;  .type   32; .endef
    .set    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long),vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::reserve(unsigned long)
    .section    .text$_Z5printI15vector_noinlineI8make_rowIJ12table_columnI7foo_auxdNS3_12value_column11field_valueEES2_IS3_iNS3_9id_column8field_idEES2_IS3_iNS3_13number_column12field_numberEEEEEEvOT_,"x"
    .linkonce discard
    .p2align 4,,15
    .globl  void print<vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&)
    .def    void print<vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&);  .scl    2;  .type   32; .endef
    .seh_proc   void print<vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&)
void print<vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&):
.LFB2177:
    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, 56
    .seh_stackalloc 56
    movaps  XMMWORD PTR 32[rsp], xmm6
    .seh_savexmm    xmm6, 32
    .seh_endprologue
    lea r13, std::ctype<char>::do_widen(char) const[rip]
    mov rbx, QWORD PTR [rcx]
    mov rbp, QWORD PTR 8[rcx]
    mov r12, QWORD PTR .refptr._ZSt4cout[rip]
    cmp rbx, rbp
    jne .L136
    jmp .L128
    .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 edx, DWORD PTR 8[rbx]
    mov rcx, r12
    mov edi, DWORD PTR 12[rbx]
    movsd   xmm6, QWORD PTR [rbx]
    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, r13
    je  .L132
    mov rcx, rsi
    call    rax
    movsx   edx, al
    jmp .L132
    .p2align 4,,10
.L128:
    movaps  xmm6, XMMWORD PTR 32[rsp]
    add rsp, 56
    pop rbx
    pop rsi
    pop rdi
    pop rbp
    pop r12
    pop r13
    ret
.L138:
    call    std::__throw_bad_cast()
    nop
    .seh_endproc
    .weak   void print<vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&)
    .def    void print<vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&);  .scl    2;  .type   32; .endef
    .set    void print<vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&),void print<vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&)
    .section    .text$_ZNSt6vectorI8make_rowIJ12table_columnI7foo_auxdNS2_12value_column11field_valueEES1_IS2_iNS2_9id_column8field_idEES1_IS2_iNS2_13number_column12field_numberEEEESaISC_EE19_M_emplace_back_auxIJRKSC_EEEvDpOT_,"x"
    .linkonce discard
    .align 2
    .p2align 4,,15
    .globl  void std::vector<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    .def    void std::vector<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&);  .scl    2;  .type   32; .endef
    .seh_proc   void std::vector<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
void std::vector<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&):
.LFB2390:
    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<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    .def    void std::vector<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&);  .scl    2;  .type   32; .endef
    .set    void std::vector<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&),void std::vector<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    .section    .text$_ZN15vector_noinlineI8make_rowIJ12table_columnI7foo_auxdNS2_12value_column11field_valueEES1_IS2_iNS2_9id_column8field_idEES1_IS2_iNS2_13number_column12field_numberEEEEE9push_backERKSC_,"x"
    .linkonce discard
    .align 2
    .p2align 4,,15
    .globl  vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    .def    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&); .scl    2;  .type   32; .endef
    .seh_proc   vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&):
.LFB2172:
    .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<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >, std::allocator<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >::_M_emplace_back_aux<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&>(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    .seh_endproc
    .weak   vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    .def    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&); .scl    2;  .type   32; .endef
    .set    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&),vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    .section    .text$_ZN9projectedI10make_tableIN7foo_aux11name_stringEJNS1_9id_columnENS1_11code_columnENS1_12value_columnENS1_13number_columnEEE6stringIJLc105ELc100ELc62ELc52ELc50EEEJ12table_columnIS1_dNS5_11field_valueEESA_IS1_iNS3_8field_idEESA_IS1_iNS6_12field_numberEEEE9to_vectorEv,"x"
    .linkonce discard
    .p2align 4,,15
    .globl  projected<make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, string<(char)105, (char)100, (char)62, (char)52, (char)50>, table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >::to_vector()
    .def    projected<make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, string<(char)105, (char)100, (char)62, (char)52, (char)50>, table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >::to_vector();  .scl    2;  .type   32; .endef
    .seh_proc   projected<make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, string<(char)105, (char)100, (char)62, (char)52, (char)50>, table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >::to_vector()
projected<make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, string<(char)105, (char)100, (char)62, (char)52, (char)50>, table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >::to_vector():
.LFB2019:
    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    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::vector_noinline()
    lea rdx, string_value<(char)115, (char)101, (char)108, (char)101, (char)99, (char)116, (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)102, (char)114, (char)111, (char)109, (char)32, (char)102, (char)111, (char)111, (char)32, (char)119, (char)104, (char)101, (char)114, (char)101, (char)32, (char)105, (char)100, (char)62, (char)52, (char)50>::value[rip]
    mov rcx, rbx
    mov DWORD PTR 32[rsp], 0
.LEHB2:
    call    dummy_db::execute(char const*)
    call    dummy_db::read_count() const [clone .isra.27]
    mov edx, eax
    mov rcx, rdi
    mov rbp, rdx
    call    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, 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 dummy_db::get<double>(unsigned int) const [clone .constprop.35]
    mov rcx, rbx
    movsd   QWORD PTR 48[rsp], xmm0
    call    int dummy_db::get<int>(unsigned int) const [clone .constprop.36]
    mov rcx, rbx
    mov DWORD PTR 56[rsp], eax
    call    int dummy_db::get<int>(unsigned int) const [clone .constprop.37]
    mov rdx, r12
    mov rcx, rdi
    mov DWORD PTR 60[rsp], eax
    call    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >::push_back(make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > const&)
    mov rcx, rbx
    add esi, 1
    call    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    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, 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
.LLSDA2019:
    .byte   0xff
    .byte   0xff
    .byte   0x1
    .uleb128 .LLSDACSE2019-.LLSDACSB2019
.LLSDACSB2019:
    .uleb128 .LEHB2-.LFB2019
    .uleb128 .LEHE2-.LEHB2
    .uleb128 .L175-.LFB2019
    .uleb128 0
    .uleb128 .LEHB3-.LFB2019
    .uleb128 .LEHE3-.LEHB3
    .uleb128 0
    .uleb128 0
.LLSDACSE2019:
    .section    .text$_ZN9projectedI10make_tableIN7foo_aux11name_stringEJNS1_9id_columnENS1_11code_columnENS1_12value_columnENS1_13number_columnEEE6stringIJLc105ELc100ELc62ELc52ELc50EEEJ12table_columnIS1_dNS5_11field_valueEESA_IS1_iNS3_8field_idEESA_IS1_iNS6_12field_numberEEEE9to_vectorEv,"x"
    .linkonce discard
    .seh_endproc
    .weak   projected<make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, string<(char)105, (char)100, (char)62, (char)52, (char)50>, table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >::to_vector()
    .def    projected<make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, string<(char)105, (char)100, (char)62, (char)52, (char)50>, table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >::to_vector();  .scl    2;  .type   32; .endef
    .set    projected<make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, string<(char)105, (char)100, (char)62, (char)52, (char)50>, table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >::to_vector(),projected<make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, string<(char)105, (char)100, (char)62, (char)52, (char)50>, table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >::to_vector()
    .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:
.LFB2013:
    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, 80
    .seh_stackalloc 80
    movaps  XMMWORD PTR 64[rsp], xmm6
    .seh_savexmm    xmm6, 64
    .seh_endprologue
    lea r13, 32[rsp]
    call    __main
    mov rcx, r13
.LEHB4:
    call    projected<make_table<foo_aux::name_string, foo_aux::id_column, foo_aux::code_column, foo_aux::value_column, foo_aux::number_column>, string<(char)105, (char)100, (char)62, (char)52, (char)50>, table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> >::to_vector()
.LEHE4:
    mov rcx, r13
.LEHB5:
    call    void print<vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > > >(vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, table_column<foo_aux, int, foo_aux::number_column::field_number> > >&&)
.LEHE5:
    mov rcx, r13
    lea r14, std::ctype<char>::do_widen(char) const[rip]
    call    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, 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, r13
    call    handwritten()
.LEHE6:
    mov rbx, QWORD PTR 32[rsp]
    mov rbp, QWORD PTR 40[rsp]
    mov r12, QWORD PTR .refptr._ZSt4cout[rip]
    cmp rbx, rbp
    jne .L193
    jmp .L187
    .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:
    mov edx, DWORD PTR 8[rbx]
    mov rcx, r12
    mov edi, DWORD PTR 12[rbx]
    movsd   xmm6, QWORD PTR [rbx]
    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, r14
    je  .L185
    mov rcx, rsi
    call    rax
    movsx   edx, al
    jmp .L185
    .p2align 4,,10
.L187:
    mov rcx, r13
    call    vector_noinline<handwritten()::Row>::~vector_noinline()
    nop
    movaps  xmm6, XMMWORD PTR 64[rsp]
    xor eax, eax
    add rsp, 80
    pop rbx
    pop rsi
    pop rdi
    pop rbp
    pop r12
    pop r13
    pop r14
    ret
.L196:
    call    std::__throw_bad_cast()
.LEHE7:
.L192:
    mov rbx, rax
    mov rcx, r13
    call    vector_noinline<handwritten()::Row>::~vector_noinline()
    mov rcx, rbx
.LEHB8:
    call    _Unwind_Resume
.L191:
    mov rbx, rax
    mov rcx, r13
    call    vector_noinline<make_row<table_column<foo_aux, double, foo_aux::value_column::field_value>, table_column<foo_aux, int, foo_aux::id_column::field_id>, 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
.LLSDA2013:
    .byte   0xff
    .byte   0xff
    .byte   0x1
    .uleb128 .LLSDACSE2013-.LLSDACSB2013
.LLSDACSB2013:
    .uleb128 .LEHB4-.LFB2013
    .uleb128 .LEHE4-.LEHB4
    .uleb128 0
    .uleb128 0
    .uleb128 .LEHB5-.LFB2013
    .uleb128 .LEHE5-.LEHB5
    .uleb128 .L191-.LFB2013
    .uleb128 0
    .uleb128 .LEHB6-.LFB2013
    .uleb128 .LEHE6-.LEHB6
    .uleb128 0
    .uleb128 0
    .uleb128 .LEHB7-.LFB2013
    .uleb128 .LEHE7-.LEHB7
    .uleb128 .L192-.LFB2013
    .uleb128 0
    .uleb128 .LEHB8-.LFB2013
    .uleb128 .LEHE8-.LEHB8
    .uleb128 0
    .uleb128 0
.LLSDACSE2013:
    .section    .text.startup,"x"
    .seh_endproc
    .p2align 4,,15
    .def    _GLOBAL__sub_I__ZNK8dummy_db3getIiEET_j;    .scl    3;  .type   32; .endef
    .seh_proc   _GLOBAL__sub_I__ZNK8dummy_db3getIiEET_j
_GLOBAL__sub_I__ZNK8dummy_db3getIiEET_j:
.LFB2560:
    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__ZNK8dummy_db3getIiEET_j
    .globl  string_value<(char)115, (char)101, (char)108, (char)101, (char)99, (char)116, (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)102, (char)114, (char)111, (char)109, (char)32, (char)102, (char)111, (char)111, (char)32, (char)119, (char)104, (char)101, (char)114, (char)101, (char)32, (char)105, (char)100, (char)62, (char)52, (char)50>::value
    .section    .rdata$_ZN12string_valueIJLc115ELc101ELc108ELc101ELc99ELc116ELc32ELc102ELc111ELc111ELc46ELc118ELc97ELc108ELc117ELc101ELc44ELc32ELc102ELc111ELc111ELc46ELc105ELc100ELc44ELc32ELc102ELc111ELc111ELc46ELc110ELc117ELc109ELc98ELc101ELc114ELc32ELc102ELc114ELc111ELc109ELc32ELc102ELc111ELc111ELc32ELc119ELc104ELc101ELc114ELc101ELc32ELc105ELc100ELc62ELc52ELc50EEE5valueE,"dr"
    .linkonce same_size
    .align 32
string_value<(char)115, (char)101, (char)108, (char)101, (char)99, (char)116, (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)102, (char)114, (char)111, (char)109, (char)32, (char)102, (char)111, (char)111, (char)32, (char)119, (char)104, (char)101, (char)114, (char)101, (char)32, (char)105, (char)100, (char)62, (char)52, (char)50>::value:
    .byte   115
    .byte   101
    .byte   108
    .byte   101
    .byte   99
    .byte   116
    .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   102
    .byte   114
    .byte   111
    .byte   109
    .byte   32
    .byte   102
    .byte   111
    .byte   111
    .byte   32
    .byte   119
    .byte   104
    .byte   101
    .byte   114
    .byte   101
    .byte   32
    .byte   105
    .byte   100
    .byte   62
    .byte   52
    .byte   50
    .byte   0
    .globl  string_value<(char)115, (char)101, (char)108, (char)101, (char)99, (char)116, (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)102, (char)114, (char)111, (char)109, (char)32, (char)102, (char)111, (char)111, (char)32, (char)119, (char)104, (char)101, (char)114, (char)101, (char)32, (char)105, (char)100, (char)62, (char)52, (char)50>::value
    .set    string_value<(char)115, (char)101, (char)108, (char)101, (char)99, (char)116, (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)102, (char)114, (char)111, (char)109, (char)32, (char)102, (char)111, (char)111, (char)32, (char)119, (char)104, (char)101, (char)114, (char)101, (char)32, (char)105, (char)100, (char)62, (char)52, (char)50>::value,string_value<(char)115, (char)101, (char)108, (char)101, (char)99, (char)116, (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)102, (char)114, (char)111, (char)109, (char)32, (char)102, (char)111, (char)111, (char)32, (char)119, (char)104, (char)101, (char)114, (char)101, (char)32, (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
Re[143]: Тормознутость и кривость linq. Compile-time EDSL DB query proof-of-conc
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 06.07.16 07:50
Оценка: +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Никакой benchmark не нужен, так как результрующий ассемблерный код в обоих вариантах идентичен, с точностью до идентификаторов — то есть истинный zero overhead


Сколько ты сэкономишь на фоне издержек сетевого стека ?
Re[144]: Тормознутость и кривость linq. Compile-time EDSL DB query proof-of-conc
От: Evgeny.Panasyuk Россия  
Дата: 06.07.16 08:33
Оценка:
Здравствуйте, Ikemefula, Вы писали:

EP>>Никакой benchmark не нужен, так как результрующий ассемблерный код в обоих вариантах идентичен, с точностью до идентификаторов — то есть истинный zero overhead

I>Сколько ты сэкономишь на фоне издержек сетевого стека ?

Здесь не имеет значения, я вообще не утверждал что это супер практично. Это пример в контексте утверждения о невозможности, впрочем твоё передёргивание вполне ожидаемо
Re[145]: Тормознутость и кривость linq. Compile-time EDSL DB query proof-of-conc
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 06.07.16 08:49
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здесь не имеет значения, я вообще не утверждал что это супер практично. Это пример в контексте утверждения о невозможности, впрочем твоё передёргивание вполне ожидаемо

Ты сделал то, что делает sqlpp.

Теперь покажи то, что делает linq.

Для затравки:
IQueryable<Foo> F(IQueryable<Foo> q, int? v) => v.HasValue ? q.Where(x => x.value == v) : q



1) Три разных типа для select, where и from не подойдут, не будет никакой композиции
2) Запрос должен быть с параметрами
3) Нужно поддерживать nullable
Re[143]: Тормознутость и кривость linq. Compile-time EDSL DB query proof-of-conc
От: artelk  
Дата: 06.07.16 10:52
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Никакой benchmark не нужен, так как результрующий ассемблерный код в обоих вариантах идентичен, с точностью до идентификаторов — то есть истинный zero overhead


Не напрягает, что SQL текстовой? Это ж сколько ценных тактиков на сервере тратится на парсинг! А еще СУБД статистику ведет, план запроса подбирает и многое другое сомнительное делает, что, в теории, можно было бы в компайл-тайм задать или вычислить — вот тут и надо бы пооптимизировать!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.