Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API has changed a bit : what is c<Type>? #1275

Open
juandent opened this issue May 2, 2024 · 1 comment
Open

API has changed a bit : what is c<Type>? #1275

juandent opened this issue May 2, 2024 · 1 comment
Labels

Comments

@juandent
Copy link
Contributor

juandent commented May 2, 2024

In column aliases, there is a relatively new way of doing things and I just wanted to make sure I understand it. The code is like this:

   struct LastResult : Result {};
   constexpr auto last_result = c<LastResult>();
    std::string sql = storage.dump(select(columns(last_result->*&LastResult::id, last_result->*&LastResult::stamp)));

Documentation says c<> creates a table reference...what is that?

Furthermore it says:

 /*
  *  Identity wrapper around a mapped object, facilitating uniform column pointer expressions.
  */
 template<class O>
 struct table_reference : std::type_identity<O> {};

What are uniform column pointer expressions? I assume this came up to support CTE?

Thanks

@trueqbit
Copy link
Collaborator

trueqbit commented May 4, 2024

  1. Table reference: A table reference is a means of hoisting a C++ class ("mapped" as a table) into sqlite_orm's type system, and facilitates legible notation of explicit "column pointers", using the over-loadable pointer-to-member operator->*().
  2. Uniformity: With CTEs you end up using a lot of explicit column pointers. The pointer-to-member operator->*() provides a very legible notation compared to column<>().
    But then we would have 3 different notations of explicitly referring to a column: column<X>(&X::x) for "mapped" classes, alias_column<A>(&X::id) for aliased tables, x_cte->*&X::id for CTEs.
    Being able to use the same notation using the pointer-to-member operator->*() for all is what I called "Uniform column pointer expressions".

You see the benefits of this notation in the description of PR #1247.

I would argue that explicit column pointer notation should be used before all others and should even be the canonical way. Writing SQL expressions requires less thinking and follows the same concept of "referencing columns"/"referring to columns" in all cases:

  1. You define a "moniker" for a result set, i.e. either table, aliased result set, or CTE.
  2. Then work with the columns of a result set using this defined moniker.

Short history for your edification:
Table references, the new way of defining tables aliases and uniform column pointer expressions arrived after the CTE feature, they were just merged before (see PR #1247 and #1144). I recognized the pattern of forming column pointers that refer to a column mapped into a CTE, using the strange but very convenient pointer-to-member operator->*(). Extending the same syntactic sugar notation to aliased tables and result sets, the original column pointers felt like 2nd-class citizens. That's when "table references" came into existence.

@fnc12 fnc12 added the question label May 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants