package org.properssl.sslcertx.mariadb.jdbc.internal.common.queryresults;
import java.io.IOException;
import org.properssl.sslcertx.mariadb.jdbc.internal.common.ColumnInformation;
import org.properssl.sslcertx.mariadb.jdbc.internal.common.PacketFetcher;
import org.properssl.sslcertx.mariadb.jdbc.internal.common.QueryException;
import org.properssl.sslcertx.mariadb.jdbc.internal.common.ServerStatus;
import org.properssl.sslcertx.mariadb.jdbc.internal.common.ValueObject;
import org.properssl.sslcertx.mariadb.jdbc.internal.common.packet.EOFPacket;
import org.properssl.sslcertx.mariadb.jdbc.internal.common.packet.ErrorPacket;
import org.properssl.sslcertx.mariadb.jdbc.internal.common.packet.RawPacket;
import org.properssl.sslcertx.mariadb.jdbc.internal.common.packet.ResultPacketFactory;
import org.properssl.sslcertx.mariadb.jdbc.internal.common.packet.ResultSetPacket;
import org.properssl.sslcertx.mariadb.jdbc.internal.common.packet.buffer.ReadUtil;
import org.properssl.sslcertx.mariadb.jdbc.internal.mysql.MySQLColumnInformation;
import org.properssl.sslcertx.mariadb.jdbc.internal.mysql.MySQLProtocol;
import org.properssl.sslcertx.mariadb.jdbc.internal.mysql.packet.MySQLRowPacket;
public class StreamingSelectResult extends SelectQueryResult {
PacketFetcher packetFetcher;
public ValueObject[] values;
MySQLProtocol protocol;
boolean isEOF;
boolean beforeFirst;
private StreamingSelectResult(ColumnInformation[] info, MySQLProtocol protocol, PacketFetcher fetcher) throws QueryException {
this.columnInformation = info;
this.protocol = protocol;
this.packetFetcher = fetcher;
this.beforeFirst = true;
this.isEOF = false;
protocol.activeResult = this;
}
/**
* create StreamingResultSet - precondition is that a result set packet has been read
*
* @param packet the result set packet from the server
* @return a StreamingQueryResult
* @throws java.io.IOException when something goes wrong while reading/writing from the server
*/
public static StreamingSelectResult createStreamingSelectResult(
ResultSetPacket packet, PacketFetcher packetFetcher, MySQLProtocol protocol)
throws IOException, QueryException {
if (protocol.activeResult != null) {
throw new QueryException("There is an active result set on the current connection, "+
"which must be closed prior to opening a new one");
}
long fieldCount = packet.getFieldCount();
ColumnInformation[] ci = new ColumnInformation[(int)fieldCount];
for (int i = 0; i < fieldCount; i++) {
final RawPacket rawPacket = packetFetcher.getRawPacket();
// We do not expect an error packet, but check it just for safety
if (ReadUtil.isErrorPacket(rawPacket)) {
ErrorPacket errorPacket = new ErrorPacket(rawPacket);
throw new QueryException("error when reading field packet " + errorPacket.getMessage(),
errorPacket.getErrorNumber(), errorPacket.getSqlState());
}
// We do not expect OK or EOF packets either
byte b = rawPacket.getByteBuffer().get(0);
if (b == 0 || b == (byte)0xfe) {
throw new QueryException("Packets out of order when trying to read field packet - " +
"got packet starting with byte " + b + "packet content (hex) = "
+ MySQLProtocol.hexdump(rawPacket.getByteBuffer(), 0));
}
try {
ci[i] = new MySQLColumnInformation(rawPacket);
} catch (Exception e) {
throw new QueryException("Error when trying to parse field packet : " + e + ",packet content (hex) = " +
MySQLProtocol.hexdump(rawPacket.getByteBuffer(), 0) , 0, "HY000", e);
}
}
RawPacket fieldEOF = packetFetcher.getRawPacket();
if (!ReadUtil.eofIsNext(fieldEOF)) {
throw new QueryException("Packets out of order when reading field packets, expected was EOF packet. " +
"Packet contents (hex) = " + MySQLProtocol.hexdump(fieldEOF.getByteBuffer(),0));
}
return new StreamingSelectResult(ci, protocol, packetFetcher);
}
@Override
public boolean next() throws IOException,QueryException{
if (isEOF)
return false;
RawPacket rawPacket = packetFetcher.getRawPacket();
if (ReadUtil.isErrorPacket(rawPacket)) {
protocol.activeResult = null;
protocol.moreResults = false;
ErrorPacket errorPacket = (ErrorPacket) ResultPacketFactory.createResultPacket(rawPacket);
throw new QueryException(errorPacket.getMessage(), errorPacket.getErrorNumber(), errorPacket.getSqlState());
}
if (ReadUtil.eofIsNext(rawPacket)) {
final EOFPacket eofPacket = (EOFPacket) ResultPacketFactory.createResultPacket(rawPacket);
protocol.activeResult = null;
protocol.moreResults = eofPacket.getStatusFlags().contains(ServerStatus.MORE_RESULTS_EXISTS);
warningCount = eofPacket.getWarningCount();
protocol.hasWarnings = (warningCount > 0);
isEOF = true;
values = null;
return false;
}
MySQLRowPacket rowPacket = new MySQLRowPacket(rawPacket, columnInformation);
values = rowPacket.getRow(packetFetcher);
return true;
}
public void close() {
super.close();
if (protocol != null && protocol.activeResult == this)
{
try {
for (;;) {
try {
if(protocol.activeResult == null) {
return;
}
if (!next())
return;
}
catch (QueryException qe) {
return;
}
catch (IOException ioe) {
return;
}
}
} finally {
protocol.activeResult = null;
protocol = null;
packetFetcher = null;
}
}
}
/**
* gets the value at position i in the result set. i starts at zero!
*
* @param i index, starts at 0
* @return
*/
@Override
public ValueObject getValueObject(int i) throws NoSuchColumnException {
return values[i];
}
public int getRows() {
return -1;
}
public boolean isBeforeFirst() {
return beforeFirst;
}
public boolean isAfterLast() {
return isEOF;
}
}