Apfelmaennchen (Mandelbrot set) and the WITH Clause #882
Replies: 2 comments 1 reply
-
Hi @trueqbit . Your work looks existing and marvelous! I'm impressed! You wrote a lot of useful text so I'll respond with a bunch of text also.
//WITH RECURSIVE
// cnt(x) AS(VALUES(1) UNION ALL SELECT x + 1 FROM cnt WHERE x < 1000000)
// SELECT x FROM cnt;
auto ast =
with(cte<cte_1>("x")(
union_all(select(from), select(column<cte_1>(0_col) + c(1), where(column<cte_1>(0_col) < end)))),
select(column<cte_1>(0_col))); looks impressive but it lacks WITH table name 'cnt'. I'd change using als_c = alias_c<Employee>;
using als_d = alias_d<Department>; This technique allows using custom aliases like this: struct alias_cnt {
static std::string_view get() { // return type can be std::string, const char * and anything that has operator<< with std::ostream
return "cnt";
}
};
// and then:
auto ast =
with(cte<alias_cnt>("x")(
union_all(select(from), select(column<alias_cnt>(0_col) + c(1), where(column<alias_cnt>(0_col) < end)))),
select(column<alias_cnt>(0_col))); Why it is important? Cause one of //WITH RECURSIVE
// parent_of(name, parent) AS
// (SELECT name, mom FROM family
// UNION
// SELECT name, dad FROM family),
// ancestor_of_alice(name) AS
// (SELECT parent FROM parent_of WHERE name = 'Alice'
// UNION ALL
// SELECT parent FROM parent_of JOIN ancestor_of_alice USING(name))
// SELECT family.name FROM ancestor_of_alice, family
// WHERE ancestor_of_alice.name = family.name
// AND died IS NULL
// ORDER BY born;
struct MyCte1 {
std::string name;
std::string parent;
};
struct MyCte2 {
std::string name;
};
auto ast =
with(make_tuple(cte<MyCte1>("parent_of", make_column("name", &MyCte1::name), make_column("parent", &MyCte1::parent))
(union_(select(columns(c_v<&Family::name>, &Family::mom)),
select(columns(&Family::name, &Family::dad)))),
cte<MyCte2>("ancestor_of_alice", make_column("name", &MyCte2::name))
(union_all(
select(&MyCte1::parent, where(column<MyCte1>(c_v<&Family::name>) == "Alice")),
select(&MyCte1::parent, join<MyCte2>(using_(column<MyCte1>(c_v<&Family::name>))))))),
select(&Family::name,
where(is_equal(&MyCte2::name, &Family::name) && is_null(&Family::died)),
order_by(&Family::born)));
auto ast = with(
make_tuple(
cte<cte_xaxis>("x")(
union_all(select(-2.0),
select(column<cte_xaxis>(0_col) + c(0.05), where(column<cte_xaxis>(0_col) < 1.2)))),
cte<cte_yaxis>("y")(
union_all(select(-1.0),
select(column<cte_yaxis>(0_col) + c(0.1), where(column<cte_yaxis>(0_col) < 1.0)))),
cte<cte_m>("iter", "cx", "cy", "x", "y")(
union_all(select(columns(0, column<cte_xaxis>(0_col), column<cte_yaxis>(0_col), 0.0, 0.0)),
select(columns(column<cte_m>(0_col) + c(1),
column<cte_m>(1_col),
column<cte_m>(2_col),
column<cte_m>(3_col) * c(column<cte_m>(3_col)) -
column<cte_m>(4_col) * c(column<cte_m>(4_col)) + column<cte_m>(1_col),
c(2.0) * column<cte_m>(3_col) * column<cte_m>(4_col) + column<cte_m>(2_col)),
where((column<cte_m>(3_col) * c(column<cte_m>(3_col)) +
column<cte_m>(4_col) * c(column<cte_m>(4_col))) < c(4.0) &&
column<cte_m>(0_col) < 28)))),
cte<cte_m2>("iter", "cx", "cy")(select(
columns(max<>(column<cte_m>(0_col)), column<cte_m>(1_col), column<cte_m>(2_col)),
group_by(column<cte_m>(1_col), column<cte_m>(2_col)))),
cte<cte_a>("t")(select(group_concat(substr(" .+*#", 1 + min<>(column<cte_m2>(0_col) / c(7.0), 4.0), 1), ""),
group_by(column<cte_m2>(2_col))))),
select(group_concat(rtrim(column<cte_a>(0_col)), "\n"))); I am waiting when someone will encode a marriage offer inside |
Beta Was this translation helpful? Give feedback.
-
I agree that we should continue working in C++17. At least in Visual Studio 2022 support even for C++20 is excellent so if possible lets move to C++17... I currently run all my sqlite_orm use in C++ latest features (which is even ahead of C++ 20) |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Apfelmaennchen (Mandelbrot set) and the WITH Clause
Hi @fn12c,
I have exciting news to announce and I think you will like it 😎!
See this output produced using sqlite_orm, driven by 'common table expressions':
This is directly taken from the documentation of SQLite's WITH Clause.
I started implementing the WITH Clause along with common table expressions (CTEs) a few weeks ago. Not sure whether it's entirely feature-complete, but I think it's time to put out word and get feedback, and start a discussion prior to a draft pull request.
Currently, the feature exists in FireDaemon's CTE branch.
Please have a look at the 'common table expression' examples located in https://github.com/FireDaemon/sqlite_orm/blob/CTEs/examples/common_table_expressions.cpp to see how all this is used.
I especially like the neat ability to select all columns from an alias and the ability to back-reference mapped columns, as shown in the 'supervisor chain' example.
BTW, here's the Apfelmaennchen select 😺!
A high-level view of how this is working:
Some apriori concepts:
For CTEs to function we need to build a temporary 'storage implementation' from the CTE's subselect. It shall purely exist during the lifetime of the actual select-statement.
So:
storage_t
methods, which operate on that with-clause expression, create the temporary 'cte expression storage'.Some implementation details that I just mention here
Along the way, in order to make all CTE examples and my use cases work, I added additional features that would make useful additions even without the CTE features.
select(asterisk<alias_a<Object>>)
]order_by(1_nth_col)
]min(X, Y, ...)
,max(X, Y, ...)
using_
to accept column pointersAdditionally I didn't hesitate to overhaul internal parts of the storage implemention lookup machinery.
(i.e. obsoleted
storage_impl<>::get_impl<>()
and storage_t<>::get_impl<>`)serializator_context_builder
was given friend access, anyone could access storage_t anyway. The much better thing I have chosen is an ADL friend function that obtains const access to the storage implementation. This allows for much better traceability. Additionally, unless necessary the better choice is to use the new access function.Questions
TODO
Beta Was this translation helpful? Give feedback.
All reactions