| // SPDX-License-Identifier: LGPL-2.1-or-later |
| // Copyright (c) 2012-2014 Monty Program Ab |
| // Copyright (c) 2015-2021 MariaDB Corporation Ab |
| |
| package org.mariadb.jdbc.message.server; |
| |
| import java.io.IOException; |
| import java.sql.SQLException; |
| import org.mariadb.jdbc.ServerPreparedStatement; |
| import org.mariadb.jdbc.client.*; |
| import org.mariadb.jdbc.client.impl.StandardReadableByteBuf; |
| import org.mariadb.jdbc.client.socket.Reader; |
| import org.mariadb.jdbc.export.Prepare; |
| import org.mariadb.jdbc.util.constants.Capabilities; |
| import org.mariadb.jdbc.util.log.Logger; |
| import org.mariadb.jdbc.util.log.Loggers; |
| |
| /** Prepare result packet See https://mariadb.com/kb/en/com_stmt_prepare/#COM_STMT_PREPARE_OK */ |
| public class PrepareResultPacket implements Completion, Prepare { |
| static final ColumnDecoder CONSTANT_PARAMETER; |
| |
| static { |
| byte[] bytes = |
| new byte[] { |
| 0x03, |
| 0x64, |
| 0x65, |
| 0x66, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x01, |
| 0x3F, |
| 0x00, |
| 0x00, |
| 0x0C, |
| 0x3F, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x06, |
| (byte) 0x80, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00 |
| }; |
| CONSTANT_PARAMETER = |
| ColumnDecoder.decode(new StandardReadableByteBuf(bytes, bytes.length), true); |
| } |
| |
| private static final Logger logger = Loggers.getLogger(PrepareResultPacket.class); |
| private final ColumnDecoder[] parameters; |
| private ColumnDecoder[] columns; |
| |
| /** prepare statement id */ |
| protected int statementId; |
| |
| /** |
| * Prepare packet constructor (parsing) |
| * |
| * @param buffer packet buffer |
| * @param reader packet reader |
| * @param context connection context |
| * @throws IOException if socket exception occurs |
| */ |
| public PrepareResultPacket(ReadableByteBuf buffer, Reader reader, Context context) |
| throws IOException { |
| boolean trace = logger.isTraceEnabled(); |
| buffer.readByte(); /* skip COM_STMT_PREPARE_OK */ |
| this.statementId = buffer.readInt(); |
| final int numColumns = buffer.readUnsignedShort(); |
| final int numParams = buffer.readUnsignedShort(); |
| this.parameters = new ColumnDecoder[numParams]; |
| this.columns = new ColumnDecoder[numColumns]; |
| |
| if (numParams > 0) { |
| for (int i = 0; i < numParams; i++) { |
| // skipping packet, since there is no metadata information. |
| // might change when https://jira.mariadb.org/browse/MDEV-15031 is done |
| parameters[i] = CONSTANT_PARAMETER; |
| reader.skipPacket(); |
| } |
| if (!context.isEofDeprecated()) { |
| reader.skipPacket(); |
| } |
| } |
| if (numColumns > 0) { |
| for (int i = 0; i < numColumns; i++) { |
| columns[i] = |
| ColumnDecoder.decode( |
| new StandardReadableByteBuf(reader.readPacket(trace)), |
| context.hasClientCapability(Capabilities.EXTENDED_TYPE_INFO)); |
| } |
| if (!context.isEofDeprecated()) { |
| reader.skipPacket(); |
| } |
| } |
| } |
| |
| /** |
| * Close prepare packet |
| * |
| * @param con current connection |
| * @throws SQLException if exception occurs |
| */ |
| public void close(Client con) throws SQLException { |
| con.closePrepare(this); |
| } |
| |
| /** |
| * Decrement use of prepare packet, so closing it if last used |
| * |
| * @param con connection |
| * @param preparedStatement current prepared statement that was using prepare object |
| * @throws SQLException if exception occurs |
| */ |
| public void decrementUse(Client con, ServerPreparedStatement preparedStatement) |
| throws SQLException { |
| close(con); |
| } |
| |
| /** |
| * Get statement id |
| * |
| * @return statement id |
| */ |
| public int getStatementId() { |
| return statementId; |
| } |
| |
| public ColumnDecoder[] getParameters() { |
| return parameters; |
| } |
| |
| public ColumnDecoder[] getColumns() { |
| return columns; |
| } |
| |
| public void setColumns(ColumnDecoder[] columns) { |
| this.columns = columns; |
| } |
| } |