Skip to content

Commit c49db58

Browse files
committed
WL#12246, DevAPI: Prepared statement support.
1 parent a5c3d29 commit c49db58

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3034
-159
lines changed

CHANGES

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
Version 8.0.16
55

6+
- WL#12246, DevAPI: Prepared statement support.
7+
68
- WL#10839, Adjust c/J tests to the new "ON" default for explicit_defaults_for_timestamp.
79

810
- Fix for Bug#29329326, PLEASE AVOID SHOW PROCESSLIST IF POSSIBLE.

src/generated/java/com/mysql/cj/x/protobuf/Mysqlx.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
// Generated by the protocol buffer compiler. DO NOT EDIT!
3333
// source: mysqlx.proto
34-
@SuppressWarnings({ "unchecked", "synthetic-access", "cast" })
34+
@SuppressWarnings({ "cast" })
3535

3636
public final class Mysqlx {
3737
private Mysqlx() {}

src/generated/java/com/mysql/cj/x/protobuf/MysqlxConnection.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program is free software; you can redistribute it and/or modify it under
55
* the terms of the GNU General Public License, version 2.0, as published by the
@@ -31,7 +31,7 @@
3131

3232
// Generated by the protocol buffer compiler. DO NOT EDIT!
3333
// source: mysqlx_connection.proto
34-
@SuppressWarnings({ "unchecked", "synthetic-access", "cast", "deprecation" })
34+
@SuppressWarnings({ "cast", "deprecation" })
3535

3636
public final class MysqlxConnection {
3737
private MysqlxConnection() {}

src/generated/java/com/mysql/cj/x/protobuf/MysqlxCrud.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
// Generated by the protocol buffer compiler. DO NOT EDIT!
3333
// source: mysqlx_crud.proto
34-
@SuppressWarnings({ "unchecked", "synthetic-access", "cast", "deprecation" })
34+
@SuppressWarnings({ "deprecation", "cast" })
3535

3636
public final class MysqlxCrud {
3737
private MysqlxCrud() {}

src/generated/java/com/mysql/cj/x/protobuf/MysqlxCursor.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
package com.mysql.cj.x.protobuf;
3131

3232
// Generated by the protocol buffer compiler. DO NOT EDIT!
33-
// source: mysqlx_crud.proto
33+
// source: mysqlx_cursor.proto
3434
@SuppressWarnings({ "cast", "deprecation" })
3535

3636
public final class MysqlxCursor {

src/generated/java/com/mysql/cj/x/protobuf/MysqlxDatatypes.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program is free software; you can redistribute it and/or modify it under
55
* the terms of the GNU General Public License, version 2.0, as published by the
@@ -31,7 +31,7 @@
3131

3232
// Generated by the protocol buffer compiler. DO NOT EDIT!
3333
// source: mysqlx_datatypes.proto
34-
@SuppressWarnings({ "unchecked", "synthetic-access", "cast" })
34+
@SuppressWarnings({ "cast" })
3535

3636
public final class MysqlxDatatypes {
3737
private MysqlxDatatypes() {}

src/generated/java/com/mysql/cj/x/protobuf/MysqlxExpect.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program is free software; you can redistribute it and/or modify it under
55
* the terms of the GNU General Public License, version 2.0, as published by the
@@ -31,7 +31,7 @@
3131

3232
// Generated by the protocol buffer compiler. DO NOT EDIT!
3333
// source: mysqlx_expect.proto
34-
@SuppressWarnings({ "unchecked", "synthetic-access", "cast" })
34+
@SuppressWarnings({ "cast" })
3535

3636
public final class MysqlxExpect {
3737
private MysqlxExpect() {}

src/generated/java/com/mysql/cj/x/protobuf/MysqlxExpr.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program is free software; you can redistribute it and/or modify it under
55
* the terms of the GNU General Public License, version 2.0, as published by the
@@ -31,7 +31,7 @@
3131

3232
// Generated by the protocol buffer compiler. DO NOT EDIT!
3333
// source: mysqlx_expr.proto
34-
@SuppressWarnings({ "unchecked", "synthetic-access", "cast", "deprecation" })
34+
@SuppressWarnings({ "cast", "deprecation" })
3535

3636
public final class MysqlxExpr {
3737
private MysqlxExpr() {}

src/generated/java/com/mysql/cj/x/protobuf/MysqlxNotice.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
// Generated by the protocol buffer compiler. DO NOT EDIT!
3333
// source: mysqlx_notice.proto
34-
@SuppressWarnings({ "unchecked", "synthetic-access", "cast", "deprecation" })
34+
@SuppressWarnings({ "cast", "deprecation" })
3535

3636
public final class MysqlxNotice {
3737
private MysqlxNotice() {}

src/generated/java/com/mysql/cj/x/protobuf/MysqlxPrepare.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
package com.mysql.cj.x.protobuf;
3131

3232
// Generated by the protocol buffer compiler. DO NOT EDIT!
33-
// source: mysqlx_notice.proto
33+
// source: mysqlx_prepare.proto
3434
@SuppressWarnings({ "cast", "deprecation" })
3535

3636
public final class MysqlxPrepare {

src/generated/java/com/mysql/cj/x/protobuf/MysqlxResultset.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
// Generated by the protocol buffer compiler. DO NOT EDIT!
3333
// source: mysqlx_resultset.proto
34-
@SuppressWarnings({ "unchecked", "synthetic-access", "cast" })
34+
@SuppressWarnings({ "cast" })
3535

3636
public final class MysqlxResultset {
3737
private MysqlxResultset() {}

src/generated/java/com/mysql/cj/x/protobuf/MysqlxSession.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
// Generated by the protocol buffer compiler. DO NOT EDIT!
3333
// source: mysqlx_session.proto
34-
@SuppressWarnings({ "unchecked", "synthetic-access", "cast" })
34+
@SuppressWarnings({ "cast" })
3535

3636
public final class MysqlxSession {
3737
private MysqlxSession() {}

src/generated/java/com/mysql/cj/x/protobuf/MysqlxSql.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program is free software; you can redistribute it and/or modify it under
55
* the terms of the GNU General Public License, version 2.0, as published by the
@@ -31,7 +31,7 @@
3131

3232
// Generated by the protocol buffer compiler. DO NOT EDIT!
3333
// source: mysqlx_sql.proto
34-
@SuppressWarnings({ "unchecked", "synthetic-access", "cast", "deprecation" })
34+
@SuppressWarnings({ "cast", "deprecation" })
3535

3636
public final class MysqlxSql {
3737
private MysqlxSql() {}

src/main/core-api/java/com/mysql/cj/protocol/ServerSession.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program is free software; you can redistribute it and/or modify it under
55
* the terms of the GNU General Public License, version 2.0, as published by the
@@ -37,7 +37,6 @@
3737
/**
3838
* Keeps the effective states of server/session variables,
3939
* contains methods for initial retrieving of these states and for their actualization.
40-
*
4140
*/
4241
public interface ServerSession {
4342

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
3+
*
4+
* This program is free software; you can redistribute it and/or modify it under
5+
* the terms of the GNU General Public License, version 2.0, as published by the
6+
* Free Software Foundation.
7+
*
8+
* This program is also distributed with certain software (including but not
9+
* limited to OpenSSL) that is licensed under separate terms, as designated in a
10+
* particular file or component or in included license documentation. The
11+
* authors of MySQL hereby grant you an additional permission to link the
12+
* program and your derivative works with the separately licensed software that
13+
* they have included with MySQL.
14+
*
15+
* Without limiting anything contained in the foregoing, this file, which is
16+
* part of MySQL Connector/J, is also subject to the Universal FOSS Exception,
17+
* version 1.0, a copy of which can be found at
18+
* http://oss.oracle.com/licenses/universal-foss-exception.
19+
*
20+
* This program is distributed in the hope that it will be useful, but WITHOUT
21+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22+
* FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
23+
* for more details.
24+
*
25+
* You should have received a copy of the GNU General Public License along with
26+
* this program; if not, write to the Free Software Foundation, Inc.,
27+
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28+
*/
29+
30+
package com.mysql.cj.util;
31+
32+
import java.util.Iterator;
33+
import java.util.Set;
34+
import java.util.TreeSet;
35+
36+
public class SequentialIdLease {
37+
private Set<Integer> sequentialIdsLease = new TreeSet<>();
38+
39+
/**
40+
* Finds and allocates the first available sequential id.
41+
*
42+
* @return the next free sequential id.
43+
*/
44+
public int allocateSequentialId() {
45+
int nextSequentialId = 0;
46+
for (Iterator<Integer> it = this.sequentialIdsLease.iterator(); it.hasNext() && nextSequentialId + 1 == it.next(); nextSequentialId++) {
47+
// Find the first free sequential id.
48+
}
49+
this.sequentialIdsLease.add(++nextSequentialId);
50+
return nextSequentialId;
51+
}
52+
53+
/**
54+
* Frees the given sequential id so that it can be reused.
55+
*
56+
* @param sequentialId
57+
* the sequential id to release
58+
*/
59+
public void releaseSequentialId(int sequentialId) {
60+
this.sequentialIdsLease.remove(sequentialId);
61+
}
62+
}

src/main/core-impl/java/com/mysql/cj/CoreSession.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program is free software; you can redistribute it and/or modify it under
55
* the terms of the GNU General Public License, version 2.0, as published by the
@@ -35,6 +35,7 @@
3535
import java.util.concurrent.CompletableFuture;
3636
import java.util.function.Function;
3737
import java.util.function.Predicate;
38+
import java.util.function.Supplier;
3839
import java.util.stream.Collector;
3940
import java.util.stream.Stream;
4041
import java.util.stream.StreamSupport;
@@ -155,8 +156,12 @@ public <M extends Message> MessageBuilder<M> getMessageBuilder() {
155156
}
156157

157158
public <QR extends QueryResult> QR sendMessage(Message message) {
159+
return sendMessage(message, this.protocol::readQueryResult);
160+
}
161+
162+
public <R> R sendMessage(Message message, Supplier<R> readResult) {
158163
this.protocol.send(message, 0);
159-
return this.protocol.readQueryResult();
164+
return readResult.get();
160165
}
161166

162167
public <QR extends QueryResult> CompletableFuture<QR> asyncSendMessage(Message message) {

src/main/core-impl/java/com/mysql/cj/MysqlxSession.java

+95-1
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,11 @@
4747
import com.mysql.cj.protocol.x.StatementExecuteOkBuilder;
4848
import com.mysql.cj.protocol.x.XMessageBuilder;
4949
import com.mysql.cj.protocol.x.XProtocol;
50+
import com.mysql.cj.protocol.x.XProtocolError;
5051
import com.mysql.cj.result.RowList;
5152
import com.mysql.cj.xdevapi.FilterParams;
53+
import com.mysql.cj.xdevapi.FilterableStatement;
54+
import com.mysql.cj.xdevapi.PreparableStatement;
5255
import com.mysql.cj.xdevapi.SqlDataResult;
5356
import com.mysql.cj.xdevapi.SqlResult;
5457
import com.mysql.cj.xdevapi.SqlResultImpl;
@@ -90,6 +93,67 @@ public void quit() {
9093
}
9194
}
9295

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+
93157
public <T extends ResultStreamer> T find(FilterParams filterParams,
94158
Function<ColumnDefinition, BiFunction<RowList, Supplier<StatementExecuteOk>, T>> resultCtor) {
95159
this.protocol.send(((XMessageBuilder) this.messageBuilder).buildFind(filterParams), 0);
@@ -99,6 +163,27 @@ public <T extends ResultStreamer> T find(FilterParams filterParams,
99163
return res;
100164
}
101165

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+
102187
public <RES_T> CompletableFuture<RES_T> asyncFind(FilterParams filterParams,
103188
Function<ColumnDefinition, BiFunction<RowList, Supplier<StatementExecuteOk>, RES_T>> resultCtor) {
104189
CompletableFuture<RES_T> f = new CompletableFuture<>();
@@ -109,6 +194,16 @@ public <RES_T> CompletableFuture<RES_T> asyncFind(FilterParams filterParams,
109194

110195
public SqlResult executeSql(String sql, List<Object> args) {
111196
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() {
112207
boolean readLastResult[] = new boolean[1];
113208
Supplier<StatementExecuteOk> okReader = () -> {
114209
if (readLastResult[0]) {
@@ -145,5 +240,4 @@ public CompletableFuture<SqlResult> asyncExecuteSql(String sql, List<Object> arg
145240
public boolean isClosed() {
146241
return !((XProtocol) this.protocol).isOpen();
147242
}
148-
149243
}

0 commit comments

Comments
 (0)