Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 5df9b35

Browse files
committed
#15 - Incorporate review feedback.
Improve Javadoc. Rename parameters for more expressiveness. Replace ASCII filtering with filter Function to move actual filtering into dialects. Original pull request: #19.
1 parent 9700c3c commit 5df9b35

File tree

5 files changed

+114
-61
lines changed

5 files changed

+114
-61
lines changed

‎src/main/java/org/springframework/data/r2dbc/dialect/BindMarkers.java‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ public interface BindMarkers {
2424
BindMarker next();
2525

2626
/**
27-
* Creates a new {@link BindMarker} that accepts a {@code nameHint}. Implementations are allowed to consider/ignore
27+
* Creates a new {@link BindMarker} that accepts a {@code hint}. Implementations are allowed to consider/ignore/filter
2828
* the name hint to create more expressive bind markers.
2929
*
30-
* @param nameHint an optional name hint.
30+
* @param hint an optional name hint that can be used as part of the bind marker.
3131
* @return a new {@link BindMarker}.
3232
*/
33-
default BindMarker next(String nameHint) {
33+
default BindMarker next(String hint) {
3434
return next();
3535
}
3636
}
Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
package org.springframework.data.r2dbc.dialect;
22

3+
import java.util.function.Function;
4+
35
import org.springframework.util.Assert;
46

57
/**
68
* This class creates new {@link BindMarkers} instances to bind parameter for a specific {@link io.r2dbc.spi.Statement}.
9+
* <p/>
10+
* Bind markers can be typically represented as placeholder and identifier. Placeholders are used within the query to
11+
* execute so the underlying database system can substitute the placeholder with the actual value. Identifiers are used
12+
* in R2DBC drivers to bind a value to a bind marker. Identifiers are typically a part of an entire bind marker when
13+
* using indexed or named bind markers.
714
*
815
* @author Mark Paluch
916
* @see BindMarkers
@@ -20,11 +27,15 @@ public interface BindMarkersFactory {
2027
BindMarkers create();
2128

2229
/**
23-
* Create index-based {@link BindMarkers}.
30+
* Create index-based {@link BindMarkers} using indexes to bind parameters. Allow customization of the bind marker
31+
* placeholder {@code prefix} to represent the bind marker as placeholder within the query.
2432
*
25-
* @param prefix bind parameter prefix.
33+
* @param prefix bind parameter prefix that is included in {@link BindMarker#getPlaceholder()} but not the actual
34+
* identifier.
2635
* @param beginWith the first index to use.
2736
* @return a {@link BindMarkersFactory} using {@code prefix} and {@code beginWith}.
37+
* @see io.r2dbc.spi.Statement#bindNull(int, Class)
38+
* @see io.r2dbc.spi.Statement#bind(int, Object)
2839
*/
2940
static BindMarkersFactory indexed(String prefix, int beginWith) {
3041

@@ -33,21 +44,49 @@ static BindMarkersFactory indexed(String prefix, int beginWith) {
3344
}
3445

3546
/**
36-
* Create named {@link BindMarkers}. Named bind markers can support {@link BindMarkers#next(String) name hints}.
37-
* Typically, named markers use name hints. If no namehint is given, named bind markers use a counter to generate
38-
* unique bind markers.
47+
* Create named {@link BindMarkers} using identifiers to bind parameters. Named bind markers can support
48+
* {@link BindMarkers#next(String) name hints}. If no {@link BindMarkers#next(String) hint} is given, named bind
49+
* markers can use a counter or a random value source to generate unique bind markers.
50+
* <p/>
51+
* Allow customization of the bind marker placeholder {@code prefix} and {@code namePrefix} to represent the bind
52+
* marker as placeholder within the query.
53+
*
54+
* @param prefix bind parameter prefix that is included in {@link BindMarker#getPlaceholder()} but not the actual
55+
* identifier.
56+
* @param namePrefix prefix for bind marker name that is included in {@link BindMarker#getPlaceholder()} and the
57+
* actual identifier.
58+
* @param maxLength maximal length of parameter names when using name hints.
59+
* @return a {@link BindMarkersFactory} using {@code prefix} and {@code beginWith}.
60+
* @see io.r2dbc.spi.Statement#bindNull(Object, Class)
61+
* @see io.r2dbc.spi.Statement#bind(Object, Object)
62+
*/
63+
static BindMarkersFactory named(String prefix, String namePrefix, int maxLength) {
64+
return named(prefix, namePrefix, maxLength, Function.identity());
65+
}
66+
67+
/**
68+
* Create named {@link BindMarkers} using identifiers to bind parameters. Named bind markers can support
69+
* {@link BindMarkers#next(String) name hints}. If no {@link BindMarkers#next(String) hint} is given, named bind
70+
* markers can use a counter or a random value source to generate unique bind markers.
3971
*
40-
* @param prefix bind parameter prefix.
41-
* @param indexPrefix prefix for bind markers that were created by incrementing a counter to generate a unique bind
42-
* marker.
43-
* @param nameLimit maximal length of parameter names when using name hints.
72+
* @param prefix bind parameter prefix that is included in {@link BindMarker#getPlaceholder()} but not the actual
73+
* identifier.
74+
* @param namePrefix prefix for bind marker name that is included in {@link BindMarker#getPlaceholder()} and the
75+
* actual identifier.
76+
* @param maxLength maximal length of parameter names when using name hints.
77+
* @param hintFilterFunction filter {@link Function} to consider database-specific limitations in bind marker/variable
78+
* names such as ASCII chars only.
4479
* @return a {@link BindMarkersFactory} using {@code prefix} and {@code beginWith}.
80+
* @see io.r2dbc.spi.Statement#bindNull(Object, Class)
81+
* @see io.r2dbc.spi.Statement#bind(Object, Object)
4582
*/
46-
static BindMarkersFactory named(String prefix, String indexPrefix, int nameLimit) {
83+
static BindMarkersFactory named(String prefix, String namePrefix, int maxLength,
84+
Function<String, String> hintFilterFunction) {
4785

4886
Assert.notNull(prefix, "Prefix must not be null!");
49-
Assert.notNull(indexPrefix, "Index prefix must not be null!");
87+
Assert.notNull(namePrefix, "Index prefix must not be null!");
88+
Assert.notNull(hintFilterFunction, "Hint filter function must not be null!");
5089

51-
return () -> new NamedBindMarkers(prefix, indexPrefix, nameLimit);
90+
return () -> new NamedBindMarkers(prefix, namePrefix, maxLength, hintFilterFunction);
5291
}
5392
}

‎src/main/java/org/springframework/data/r2dbc/dialect/NamedBindMarkers.java‎

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import io.r2dbc.spi.Statement;
44

55
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
6+
import java.util.function.Function;
67

78
import org.springframework.util.Assert;
89

@@ -21,17 +22,24 @@ class NamedBindMarkers implements BindMarkers {
2122

2223
private final String prefix;
2324

24-
private final String indexPrefix;
25+
private final String namePrefix;
2526

2627
private final int nameLimit;
2728

28-
NamedBindMarkers(String prefix, String indexPrefix, int nameLimit) {
29+
private final Function<String, String> hintFilterFunction;
30+
31+
NamedBindMarkers(String prefix, String namePrefix, int nameLimit, Function<String, String> hintFilterFunction) {
2932

3033
this.prefix = prefix;
31-
this.indexPrefix = indexPrefix;
34+
this.namePrefix = namePrefix;
3235
this.nameLimit = nameLimit;
36+
this.hintFilterFunction = hintFilterFunction;
3337
}
3438

39+
/*
40+
* (non-Javadoc)
41+
* @see org.springframework.data.r2dbc.dialect.BindMarkers#next()
42+
*/
3543
@Override
3644
public BindMarker next() {
3745

@@ -40,18 +48,16 @@ public BindMarker next() {
4048
return new NamedBindMarker(prefix + name, name);
4149
}
4250

51+
/*
52+
* (non-Javadoc)
53+
* @see org.springframework.data.r2dbc.dialect.BindMarkers#next(java.lang.String)
54+
*/
4355
@Override
44-
public BindMarker next(String nameHint) {
45-
46-
Assert.notNull(nameHint, "Name hint must not be null");
56+
public BindMarker next(String hint) {
4757

48-
String name = nextName();
49-
50-
String filteredNameHint = filter(nameHint);
58+
Assert.notNull(hint, "Name hint must not be null");
5159

52-
if (!filteredNameHint.isEmpty()) {
53-
name += "_" + filteredNameHint;
54-
}
60+
String name = nextName() + hintFilterFunction.apply(hint);
5561

5662
if (name.length() > nameLimit) {
5763
name = name.substring(0, nameLimit);
@@ -63,25 +69,7 @@ public BindMarker next(String nameHint) {
6369
private String nextName() {
6470

6571
int index = COUNTER_INCREMENTER.getAndIncrement(this);
66-
return indexPrefix + index;
67-
}
68-
69-
private static String filter(CharSequence input) {
70-
71-
StringBuilder builder = new StringBuilder();
72-
73-
for (int i = 0; i < input.length(); i++) {
74-
75-
char ch = input.charAt(i);
76-
77-
// ascii letter or digit
78-
if (Character.isLetterOrDigit(ch) && ch < 127) {
79-
builder.append(ch);
80-
}
81-
82-
}
83-
84-
return builder.toString();
72+
return namePrefix + index;
8573
}
8674

8775
/**

‎src/test/java/org/springframework/data/r2dbc/dialect/IndexedBindMarkersUnitTests.java‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,18 @@ public void shouldCreateNewBindMarkers() {
2929
@Test // gh-15
3030
public void nextShouldIncrementBindMarker() {
3131

32-
BindMarkers bindMarkers = BindMarkersFactory.indexed("$", 0).create();
32+
String[] prefixes = { "$", "?" };
33+
34+
for (String prefix : prefixes) {
35+
36+
BindMarkers bindMarkers = BindMarkersFactory.indexed(prefix, 0).create();
3337

34-
BindMarker marker1 = bindMarkers.next();
35-
BindMarker marker2 = bindMarkers.next();
38+
BindMarker marker1 = bindMarkers.next();
39+
BindMarker marker2 = bindMarkers.next();
3640

37-
assertThat(marker1.getPlaceholder()).isEqualTo("0ドル");
38-
assertThat(marker2.getPlaceholder()).isEqualTo("1ドル");
41+
assertThat(marker1.getPlaceholder()).isEqualTo(prefix + "0");
42+
assertThat(marker2.getPlaceholder()).isEqualTo(prefix + "1");
43+
}
3944
}
4045

4146
@Test // gh-15

‎src/test/java/org/springframework/data/r2dbc/dialect/NamedBindMarkersUnitTests.java‎

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,46 @@ public void shouldCreateNewBindMarkers() {
2929
@Test // gh-15
3030
public void nextShouldIncrementBindMarker() {
3131

32-
BindMarkersbindMarkers = BindMarkersFactory.named("@", "p", 32).create();
32+
String[] prefixes = { "$", "?" };
3333

34-
BindMarker marker1 = bindMarkers.next();
35-
BindMarker marker2 = bindMarkers.next();
34+
for (String prefix : prefixes) {
3635

37-
assertThat(marker1.getPlaceholder()).isEqualTo("@p0");
38-
assertThat(marker2.getPlaceholder()).isEqualTo("@p1");
36+
BindMarkers bindMarkers = BindMarkersFactory.named(prefix, "p", 32).create();
37+
38+
BindMarker marker1 = bindMarkers.next();
39+
BindMarker marker2 = bindMarkers.next();
40+
41+
assertThat(marker1.getPlaceholder()).isEqualTo(prefix + "p0");
42+
assertThat(marker2.getPlaceholder()).isEqualTo(prefix + "p1");
43+
}
3944
}
4045

4146
@Test // gh-15
4247
public void nextShouldConsiderNameHint() {
4348

44-
BindMarkers bindMarkers = BindMarkersFactory.named("@", "p", 32).create();
49+
BindMarkers bindMarkers = BindMarkersFactory.named("@", "x", 32).create();
50+
51+
BindMarker marker1 = bindMarkers.next("foo1bar");
52+
BindMarker marker2 = bindMarkers.next();
4553

46-
BindMarker marker1 = bindMarkers.next("foo.bar?");
54+
assertThat(marker1.getPlaceholder()).isEqualTo("@x0foo1bar");
55+
assertThat(marker2.getPlaceholder()).isEqualTo("@x1");
56+
}
57+
58+
@Test // gh-15
59+
public void nextShouldConsiderFilteredNameHint() {
60+
61+
BindMarkers bindMarkers = BindMarkersFactory.named("@", "p", 32, s -> {
62+
63+
return s.chars().filter(Character::isAlphabetic)
64+
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();
65+
66+
}).create();
67+
68+
BindMarker marker1 = bindMarkers.next("foo1.bar?");
4769
BindMarker marker2 = bindMarkers.next();
4870

49-
assertThat(marker1.getPlaceholder()).isEqualTo("@p0_foobar");
71+
assertThat(marker1.getPlaceholder()).isEqualTo("@p0foobar");
5072
assertThat(marker2.getPlaceholder()).isEqualTo("@p1");
5173
}
5274

@@ -57,7 +79,7 @@ public void nextShouldConsiderNameLimit() {
5779

5880
BindMarker marker1 = bindMarkers.next("123456789");
5981

60-
assertThat(marker1.getPlaceholder()).isEqualTo("@p0_1234567");
82+
assertThat(marker1.getPlaceholder()).isEqualTo("@p012345678");
6183
}
6284

6385
@Test // gh-15
@@ -82,7 +104,6 @@ public void bindNullShouldBindByName() {
82104
BindMarkers bindMarkers = BindMarkersFactory.named("@", "p", 32).create();
83105

84106
bindMarkers.next(); // ignore
85-
86107
bindMarkers.next().bindNull(statement, Integer.class);
87108

88109
verify(statement).bindNull("p1", Integer.class);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /