16
16
17
17
package io .r2dbc .postgresql .client ;
18
18
19
+ import io .netty .buffer .ByteBuf ;
20
+ import io .netty .buffer .ByteBufAllocator ;
19
21
import io .netty .buffer .Unpooled ;
20
22
import io .r2dbc .postgresql .message .Format ;
21
23
import io .r2dbc .postgresql .message .backend .BackendMessage ;
35
37
36
38
import java .util .Collection ;
37
39
import java .util .Collections ;
38
- import java .util .List ;
40
+ import java .util .Objects ;
39
41
import java .util .function .Predicate ;
40
42
import java .util .regex .Pattern ;
41
43
@@ -71,15 +73,22 @@ private ExtendedQueryMessageFlow() {
71
73
* @return the messages received in response to the exchange
72
74
* @throws IllegalArgumentException if {@code bindings}, {@code client}, {@code portalNameSupplier}, or {@code statementName} is {@code null}
73
75
*/
74
- public static Flux <BackendMessage > execute (Publisher <Binding > bindings , Client client , PortalNameSupplier portalNameSupplier , String statementName , String query , boolean forceBinary ) {
76
+ public static Flux <BackendMessage > execute (Collection <Binding > bindings , Client client , PortalNameSupplier portalNameSupplier , String statementName , String query , boolean forceBinary ) {
75
77
Assert .requireNonNull (bindings , "bindings must not be null" );
76
78
Assert .requireNonNull (client , "client must not be null" );
77
79
Assert .requireNonNull (portalNameSupplier , "portalNameSupplier must not be null" );
78
80
Assert .requireNonNull (statementName , "statementName must not be null" );
79
81
80
- return client .exchange (Flux .from (bindings )
81
- .flatMap (binding -> toBindFlow (binding , portalNameSupplier , statementName , query , forceBinary ))
82
- .concatWith (Mono .just (Sync .INSTANCE )));
82
+ if (bindings .size () == 1 ) {
83
+
84
+ Binding binding = bindings .iterator ().next ();
85
+ return client .exchange (toBindFlow (binding , portalNameSupplier , statementName , query , forceBinary , true ));
86
+ } else {
87
+
88
+ return client .exchange (Flux .fromIterable (bindings )
89
+ .flatMap (binding -> toBindFlow (binding , portalNameSupplier , statementName , query , forceBinary , false ))
90
+ .concatWith (Mono .just (Sync .INSTANCE )));
91
+ }
83
92
}
84
93
85
94
/**
@@ -92,7 +101,7 @@ public static Flux<BackendMessage> execute(Publisher<Binding> bindings, Client c
92
101
* @return the messages received in response to this exchange
93
102
* @throws IllegalArgumentException if {@code client}, {@code name}, {@code query}, or {@code types} is {@code null}
94
103
*/
95
- public static Flux <BackendMessage > parse (Client client , String name , String query , List < Integer > types ) {
104
+ public static Flux <BackendMessage > parse (Client client , String name , String query , int [] types ) {
96
105
Assert .requireNonNull (client , "client must not be null" );
97
106
Assert .requireNonNull (name , "name must not be null" );
98
107
Assert .requireNonNull (query , "query must not be null" );
@@ -110,24 +119,138 @@ private static Collection<Format> resultFormat(boolean forceBinary) {
110
119
}
111
120
}
112
121
113
- private static Flux <FrontendMessage > toBindFlow (Binding binding , PortalNameSupplier portalNameSupplier , String statementName , String query , boolean forceBinary ) {
122
+ private static Publisher <FrontendMessage > toBindFlow (Binding binding , PortalNameSupplier portalNameSupplier , String statementName , String query , boolean forceBinary , boolean inlineSync ) {
114
123
String portal = portalNameSupplier .get ();
115
-
116
- return Flux .fromIterable (binding .getParameterValues ())
124
+ return binding .parameterValues ()
117
125
.flatMap (f -> {
118
126
if (f == Parameter .NULL_VALUE ) {
119
127
return Flux .just (Bind .NULL_VALUE );
128
+ } else if (f instanceof Mono ) {
129
+ return f ;
120
130
} else {
121
131
return Flux .from (f )
122
132
.reduce (Unpooled .compositeBuffer (), (c , b ) -> c .addComponent (true , b ));
123
133
}
124
134
})
125
135
.collectList ()
126
- .flatMapMany (values -> {
136
+ .map (values -> {
127
137
Bind bind = new Bind (portal , binding .getParameterFormats (), values , resultFormat (forceBinary ), statementName );
128
138
129
- return Flux .just (bind , new Describe (portal , PORTAL ), new Execute (portal , NO_LIMIT ), new Close (portal , PORTAL ));
139
+ if (inlineSync ) {
140
+ return new BindDescribeExecuteSyncClose (bind , portal );
141
+ }
142
+
143
+ return new BindDescribeExecuteClose (bind , portal );
130
144
}).doOnSubscribe (ignore -> QueryLogger .logQuery (query ));
131
145
}
132
146
147
+ public static class BindDescribeExecuteSyncClose implements FrontendMessage {
148
+
149
+ private final Bind bind ;
150
+
151
+ private final String portal ;
152
+
153
+ public BindDescribeExecuteSyncClose (Bind bind , String portal ) {
154
+
155
+ this .bind = bind ;
156
+ this .portal = portal ;
157
+ }
158
+
159
+ @ Override
160
+ public Publisher <ByteBuf > encode (ByteBufAllocator byteBufAllocator ) {
161
+
162
+ return Mono .fromSupplier (() -> {
163
+
164
+ ByteBuf buffer = byteBufAllocator .buffer (4 * 32 );
165
+
166
+ this .bind .encode (buffer );
167
+ Describe .encode (buffer , this .portal , PORTAL );
168
+ Execute .encode (buffer , this .portal , NO_LIMIT );
169
+ Sync .INSTANCE .encode (buffer );
170
+ Close .encode (buffer , this .portal , PORTAL );
171
+ return buffer ;
172
+ });
173
+ }
174
+
175
+ @ Override
176
+ public boolean equals (Object o ) {
177
+ if (this == o ) {
178
+ return true ;
179
+ }
180
+ if (!(o instanceof BindDescribeExecuteSyncClose )) {
181
+ return false ;
182
+ }
183
+ BindDescribeExecuteSyncClose that = (BindDescribeExecuteSyncClose ) o ;
184
+ return Objects .equals (this .bind , that .bind ) &&
185
+ Objects .equals (this .portal , that .portal );
186
+ }
187
+
188
+ @ Override
189
+ public int hashCode () {
190
+ return Objects .hash (this .bind , this .portal );
191
+ }
192
+
193
+ @ Override
194
+ public String toString () {
195
+ return "BindDescExecSyncClose{" +
196
+ "bind=" + this .bind +
197
+ ", portal='" + this .portal + '\'' +
198
+ '}' ;
199
+ }
200
+ }
201
+
202
+ public static class BindDescribeExecuteClose implements FrontendMessage {
203
+
204
+ private final Bind bind ;
205
+
206
+ private final String portal ;
207
+
208
+ public BindDescribeExecuteClose (Bind bind , String portal ) {
209
+
210
+ this .bind = bind ;
211
+ this .portal = portal ;
212
+ }
213
+
214
+ @ Override
215
+ public Publisher <ByteBuf > encode (ByteBufAllocator byteBufAllocator ) {
216
+
217
+ return Mono .fromSupplier (() -> {
218
+
219
+ ByteBuf buffer = byteBufAllocator .buffer (4 * 32 );
220
+
221
+ this .bind .encode (buffer );
222
+ Describe .encode (buffer , this .portal , PORTAL );
223
+ Execute .encode (buffer , this .portal , NO_LIMIT );
224
+ Close .encode (buffer , this .portal , PORTAL );
225
+ return buffer ;
226
+ });
227
+ }
228
+
229
+ @ Override
230
+ public boolean equals (Object o ) {
231
+ if (this == o ) {
232
+ return true ;
233
+ }
234
+ if (!(o instanceof BindDescribeExecuteClose )) {
235
+ return false ;
236
+ }
237
+ BindDescribeExecuteClose that = (BindDescribeExecuteClose ) o ;
238
+ return Objects .equals (this .bind , that .bind ) &&
239
+ Objects .equals (this .portal , that .portal );
240
+ }
241
+
242
+ @ Override
243
+ public int hashCode () {
244
+ return Objects .hash (this .bind , this .portal );
245
+ }
246
+
247
+ @ Override
248
+ public String toString () {
249
+ return "BindDescExecClose{" +
250
+ "bind=" + this .bind +
251
+ ", portal='" + this .portal + '\'' +
252
+ '}' ;
253
+ }
254
+ }
255
+
133
256
}
0 commit comments