47
47
import com .mysql .cj .protocol .x .StatementExecuteOkBuilder ;
48
48
import com .mysql .cj .protocol .x .XMessageBuilder ;
49
49
import com .mysql .cj .protocol .x .XProtocol ;
50
+ import com .mysql .cj .protocol .x .XProtocolError ;
50
51
import com .mysql .cj .result .RowList ;
51
52
import com .mysql .cj .xdevapi .FilterParams ;
53
+ import com .mysql .cj .xdevapi .FilterableStatement ;
54
+ import com .mysql .cj .xdevapi .PreparableStatement ;
52
55
import com .mysql .cj .xdevapi .SqlDataResult ;
53
56
import com .mysql .cj .xdevapi .SqlResult ;
54
57
import com .mysql .cj .xdevapi .SqlResultImpl ;
@@ -90,6 +93,67 @@ public void quit() {
90
93
}
91
94
}
92
95
96
+ /**
97
+ * Consume an OK packet from the underlying protocol.
98
+ *
99
+ * @return <code>null</code>
100
+ */
101
+ public Void readOk () {
102
+ ((XProtocol ) this .protocol ).readOk ();
103
+ return null ;
104
+ }
105
+
106
+ /**
107
+ * Check if current session is using a MySQL server that supports prepared statements.
108
+ *
109
+ * @return
110
+ * {@code true} if the MySQL server in use supports prepared statements
111
+ */
112
+ public boolean supportsPreparedStatements () {
113
+ return ((XProtocol ) this .protocol ).supportsPreparedStatements ();
114
+ }
115
+
116
+ /**
117
+ * Check if enough statements were executed in the underlying MySQL server so that another prepare statement attempt should be done.
118
+ *
119
+ * @return
120
+ * {@code true} if enough executions have been done since last time a prepared statement failed to be prepared
121
+ */
122
+ public boolean readyForPreparingStatements () {
123
+ return ((XProtocol ) this .protocol ).readyForPreparingStatements ();
124
+ }
125
+
126
+ /**
127
+ * Return an id to be used as a client-managed prepared statement id.
128
+ *
129
+ * @return a new identifier to be used as prepared statement id
130
+ */
131
+ public int getNewPreparedStatementId (PreparableStatement <?> preparableStatement ) {
132
+ return ((XProtocol ) this .protocol ).getNewPreparedStatementId (preparableStatement );
133
+ }
134
+
135
+ /**
136
+ * Free a prepared statement id so that it can be reused.
137
+ *
138
+ * @param preparedStatementId
139
+ * the prepared statement id to release
140
+ */
141
+ public void freePreparedStatementId (int preparedStatementId ) {
142
+ ((XProtocol ) this .protocol ).freePreparedStatementId (preparedStatementId );
143
+ }
144
+
145
+ /**
146
+ * Propagate to the underlying protocol instance that preparing a statement on the connected server failed.
147
+ *
148
+ * @param preparedStatementId
149
+ * the id of the prepared statement that failed to be prepared
150
+ * @return
151
+ * {@code true} if the exception was properly handled
152
+ */
153
+ public boolean failedPreparingStatement (int preparedStatementId , XProtocolError e ) {
154
+ return ((XProtocol ) this .protocol ).failedPreparingStatement (preparedStatementId , e );
155
+ }
156
+
93
157
public <T extends ResultStreamer > T find (FilterParams filterParams ,
94
158
Function <ColumnDefinition , BiFunction <RowList , Supplier <StatementExecuteOk >, T >> resultCtor ) {
95
159
this .protocol .send (((XMessageBuilder ) this .messageBuilder ).buildFind (filterParams ), 0 );
@@ -99,6 +163,27 @@ public <T extends ResultStreamer> T find(FilterParams filterParams,
99
163
return res ;
100
164
}
101
165
166
+ /**
167
+ * Execute a previously prepared find statement using the given arguments.
168
+ *
169
+ * @param preparedStatementId
170
+ * the prepared statement id to execute. This statement must be previously prepared
171
+ * @param filterParams
172
+ * the {@link FilterableStatement} params that contain the arguments for the previously-defined placeholders
173
+ * @param resultCtor
174
+ * a constructor that builds the results.
175
+ * @return
176
+ * the result from the given constructor
177
+ */
178
+ public <T extends ResultStreamer > T executePreparedFind (int preparedStatementId , FilterParams filterParams ,
179
+ Function <ColumnDefinition , BiFunction <RowList , Supplier <StatementExecuteOk >, T >> resultCtor ) {
180
+ this .protocol .send (((XMessageBuilder ) this .messageBuilder ).buildPrepareExecute (preparedStatementId , filterParams ), 0 );
181
+ ColumnDefinition metadata = this .protocol .readMetadata ();
182
+ T res = resultCtor .apply (metadata ).apply (((XProtocol ) this .protocol ).getRowInputStream (metadata ), this .protocol ::readQueryResult );
183
+ this .protocol .setCurrentResultStreamer (res );
184
+ return res ;
185
+ }
186
+
102
187
public <RES_T > CompletableFuture <RES_T > asyncFind (FilterParams filterParams ,
103
188
Function <ColumnDefinition , BiFunction <RowList , Supplier <StatementExecuteOk >, RES_T >> resultCtor ) {
104
189
CompletableFuture <RES_T > f = new CompletableFuture <>();
@@ -109,6 +194,16 @@ public <RES_T> CompletableFuture<RES_T> asyncFind(FilterParams filterParams,
109
194
110
195
public SqlResult executeSql (String sql , List <Object > args ) {
111
196
this .protocol .send (this .messageBuilder .buildSqlStatement (sql , args ), 0 );
197
+ return executeSqlProcessResult ();
198
+ }
199
+
200
+ /**
201
+ * Process the response messages from a <i>StmtExecute</i> request.
202
+ *
203
+ * @return
204
+ * an {@link SqlResult} with the returned rows.
205
+ */
206
+ private SqlResult executeSqlProcessResult () {
112
207
boolean readLastResult [] = new boolean [1 ];
113
208
Supplier <StatementExecuteOk > okReader = () -> {
114
209
if (readLastResult [0 ]) {
@@ -145,5 +240,4 @@ public CompletableFuture<SqlResult> asyncExecuteSql(String sql, List<Object> arg
145
240
public boolean isClosed () {
146
241
return !((XProtocol ) this .protocol ).isOpen ();
147
242
}
148
-
149
243
}
0 commit comments