/** * Copyright (C) 2009-2013 FoundationDB, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.foundationdb.sql.pg; import java.io.InputStream; import java.io.IOException; public class PostgresCopyInputStream extends InputStream { private PostgresMessenger messenger; private byte[] message; private int length, pos; private boolean eof; public PostgresCopyInputStream(PostgresMessenger messenger, int ncols) throws IOException { this.messenger = messenger; messenger.beginMessage(PostgresMessages.COPY_IN_RESPONSE_TYPE.code()); messenger.writeByte(0); // textual messenger.writeShort((short)ncols); for (int i = 0; i < ncols; i++) { messenger.writeShort(0); // text } messenger.sendMessage(true); } @Override public int read() throws IOException { while (true) { if (pos < length) return message[pos++]; if (!nextMessage()) return -1; } } @Override public int read(byte b[], int off, int len) throws IOException { if (len == 0) return 0; while (true) { int nb = length - pos; if (nb > 0) { if (nb > len) nb = len; System.arraycopy(message, pos, b, off, nb); pos += nb; return nb; } if (!nextMessage()) return -1; } } @Override public long skip(long n) throws IOException { if (n <= 0) return 0; long skipped = 0; while (true) { int nb = length - pos; if (nb > 0) { if (nb > n) nb = (int)n; pos += nb; skipped += nb; n -= nb; if (n <= 0) break; } if (!nextMessage()) break; } return skipped; } @Override public int available() throws IOException { return (length - pos); } private boolean nextMessage() throws IOException { while (true) { switch (messenger.readMessage()) { case COPY_DATA_TYPE: message = messenger.getRawMessage(); pos = 0; length = message.length; return true; case COPY_DONE_TYPE: return false; case COPY_FAIL_TYPE: throw new IOException("Copy failed: " + messenger.readString()); case FLUSH_TYPE: case SYNC_TYPE: break; default: throw new IOException("Unexpected message type"); } } } }