Skip to content

Commit 1e3b7d9

Browse files
committed
add +~+ fragment concat op
1 parent 34ca0df commit 1e3b7d9

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

modules/core/src/main/scala/doobie/util/fragment.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,23 @@ object fragment {
5757
def ++(fb: Fragment): Fragment =
5858
new Fragment(sql + fb.sql, elems ++ fb.elems, pos orElse fb.pos)
5959

60+
/** Concatenate this fragment with another, yielding a larger fragment and making sure there is at least one
61+
* whitespace between the source fragments.
62+
*/
63+
def +~+(that: Fragment): Fragment = {
64+
val res =
65+
if (sql.isEmpty) that.sql
66+
else if (that.sql.isEmpty) sql
67+
else if (sql.last.isWhitespace || that.sql.head.isWhitespace) sql + that.sql
68+
else sql + " " + that.sql
69+
70+
new Fragment(
71+
res,
72+
elems ++ that.elems,
73+
pos orElse that.pos
74+
)
75+
}
76+
6077
def stripMargin(marginChar: Char): Fragment =
6178
new Fragment(sql.stripMargin(marginChar), elems, pos)
6279

modules/core/src/test/scala/doobie/util/FragmentSuite.scala

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44

55
package doobie.util
66

7-
import cats.syntax.all.*
87
import cats.effect.IO
8+
import cats.syntax.all.*
99
import doobie.*
10+
import doobie.Fragment.const0
1011
import doobie.implicits.*
1112
import doobie.testutils.VoidExtensions
1213
import munit.CatsEffectSuite
@@ -33,9 +34,25 @@ class FragmentSuite extends CatsEffectSuite {
3334
assertEquals(fr"foo $a $b bar".query[Unit].sql, "foo ? ? bar ")
3435
}
3536

36-
test("Fragment must concatenate properly") {
37+
test("Fragment builders DO NOT treat backslashes as escape characters") {
38+
assertEquals(fr0"foo\\bar".query[Unit].sql, """foo\\bar""")
39+
assertEquals(fr0"foo\nbar".query[Unit].sql, """foo\nbar""")
40+
}
41+
test("Fragment must concatenate properly with `++`") {
3742
assertEquals((fr"foo" ++ fr"bar $a baz").query[Unit].sql, "foo bar ? baz ")
3843
}
44+
test("Fragment must concatenate properly enforcing at least 1 whitespace in between with `+~+`") {
45+
// Since `fr"..."` do not parse backslashes as escape characters, so we need to use `const0` to test them.
46+
assertEquals((const0("") +~+ const0("bar")).query[Unit].sql, "bar")
47+
assertEquals((const0("foo") +~+ const0("")).query[Unit].sql, "foo")
48+
assertEquals((const0("foo") +~+ const0("bar")).query[Unit].sql, "foo bar")
49+
assertEquals((const0("foo ") +~+ const0("bar")).query[Unit].sql, "foo bar")
50+
assertEquals((const0("foo\n") +~+ const0("bar")).query[Unit].sql, "foo\nbar")
51+
assertEquals((const0("foo") +~+ const0(" bar")).query[Unit].sql, "foo bar")
52+
assertEquals((const0("foo") +~+ const0("\tbar")).query[Unit].sql, "foo\tbar")
53+
assertEquals((const0("foo ") +~+ const0(" bar")).query[Unit].sql, "foo bar")
54+
assertEquals((const0("foo\r") +~+ const0("\fbar")).query[Unit].sql, "foo\r\fbar")
55+
}
3956

4057
test("Fragment must interpolate fragments properly") {
4158
assertEquals(fr"foo ${fr0"bar $a baz"}".query[Unit].sql, "foo bar ? baz ")

0 commit comments

Comments
 (0)