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

Propose a fragment concat operator that ensures a whitespace in between #2166

Merged
merged 2 commits into from
Feb 3, 2025

Conversation

satorg
Copy link
Contributor

@satorg satorg commented Jan 14, 2025

This PR proposes a new operator +~+ for fragments concatenation that makes sure that there is at least 1 whitespace between the fragments being concatenated. I realize, this proposal is going to be a controversial one. However I decided to give it a shot.

Motivation

I've been working with Doobie for quite a while and use its fragment API to create pretty sophisticated queries. Some of those queries are created dynamically, i.e. various parts of the SQL are concatenated depending on some external conditions. With time I started getting a feeling that the whole fr/fr0/const/const0 paradigm might not be the great idea at all. When I create a fragment that may or may not be concatenated with something else later, I don't really want to worry about whether I have to end it with a whitespace or not. I do cary though about the whitespace at the moment when the concatenation happens, if it is the case. So this is where the idea of the proposed operator comes from: instead of keeping track of previous fragments endings, we can simply use fr0 and const0 everywhere along with either ++ or +~+ operators, depending on a particular case. For example:

// Consider it returns something like `SELECT ... FROM foo JOIN bar ON whatever`
def baseSelectSQL: Fragment = ???

def conditionalSelectSQL(one: Option[Int], two: Option[Int]) =
  baseSelectSQL +~+
    andOpt(
      one.map(a => fr0"one = $one"),
      two.map(b => fr0"two = $b)
    ).fold(Fragment.empty)(fr0"WHERE" +~+ _)

In other words, with +~+ operator we should never worry about adding explicit whitespaces anywhere anymore – the operator will take care of it automatically. Thereby the code becomes clearer and SQL logs (if employed) become less cluttered.

About the Naming

My initial intent was to give the operator this name: +_+. Unfortunately, Scala parser has its own business with underscores in operator-alike names and such a name cannot be used without backticks. So I ended up with something that is relatively simple and self-explanatory.

However, if there is a chance that the PR can be accepted, I'm generally open to any other (better) name, so feel free to suggest other options please.

@jatcwang
Copy link
Collaborator

Thanks for the PR! I agree that this is very useful.

@satorg satorg requested a review from jatcwang February 3, 2025 08:38
@jatcwang
Copy link
Collaborator

jatcwang commented Feb 3, 2025

Thanks a lot!

@jatcwang jatcwang merged commit a3b4087 into typelevel:main Feb 3, 2025
5 checks passed
@satorg satorg deleted the new-fragment-ops branch February 3, 2025 21:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants