java/sql-dk/src/main/java/info/globalcode/sql/dk/batch/BatchDecoder.java
author František Kučera <franta-hg@frantovo.cz>
Sun, 04 Feb 2024 16:10:37 +0100
branchv_0
changeset 255 099bb96f8d8d
parent 250 aae5009bd0af
permissions -rw-r--r--
tabular formatter: new option 'separateBy' to print horizontal separator on each change of given column
franta-hg@146
     1
/**
franta-hg@146
     2
 * SQL-DK
franta-hg@146
     3
 * Copyright © 2014 František Kučera (frantovo.cz)
franta-hg@146
     4
 *
franta-hg@146
     5
 * This program is free software: you can redistribute it and/or modify
franta-hg@146
     6
 * it under the terms of the GNU General Public License as published by
franta-hg@250
     7
 * the Free Software Foundation, version 3 of the License.
franta-hg@146
     8
 *
franta-hg@146
     9
 * This program is distributed in the hope that it will be useful,
franta-hg@146
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
franta-hg@146
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
franta-hg@146
    12
 * GNU General Public License for more details.
franta-hg@146
    13
 *
franta-hg@146
    14
 * You should have received a copy of the GNU General Public License
franta-hg@146
    15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
franta-hg@146
    16
 */
franta-hg@146
    17
package info.globalcode.sql.dk.batch;
franta-hg@146
    18
franta-hg@146
    19
import info.globalcode.sql.dk.Parameter;
franta-hg@146
    20
import info.globalcode.sql.dk.SQLCommand;
franta-hg@146
    21
import info.globalcode.sql.dk.SQLCommandNumbered;
franta-hg@146
    22
import java.io.DataInputStream;
franta-hg@146
    23
import java.io.InputStream;
franta-hg@146
    24
import static info.globalcode.sql.dk.batch.BatchConstants.*;
franta-hg@146
    25
import static info.globalcode.sql.dk.Functions.toHex;
franta-hg@146
    26
import info.globalcode.sql.dk.SQLType;
franta-hg@146
    27
import java.io.IOException;
franta-hg@146
    28
import java.util.ArrayList;
franta-hg@146
    29
import java.util.Arrays;
franta-hg@146
    30
import java.util.List;
franta-hg@146
    31
franta-hg@146
    32
/**
franta-hg@146
    33
 *
franta-hg@146
    34
 * @author Ing. František Kučera (frantovo.cz)
franta-hg@146
    35
 */
franta-hg@146
    36
public class BatchDecoder {
franta-hg@146
    37
franta-hg@146
    38
	public Batch decode(InputStream in) throws BatchException {
franta-hg@146
    39
		return new BatchFromStream(new DataInputStream(in));
franta-hg@146
    40
	}
franta-hg@146
    41
franta-hg@146
    42
	private class BatchFromStream implements Batch {
franta-hg@146
    43
franta-hg@146
    44
		private DataInputStream in;
franta-hg@146
    45
		private boolean hasNext;
franta-hg@146
    46
franta-hg@146
    47
		public BatchFromStream(DataInputStream in) throws BatchException {
franta-hg@146
    48
			this.in = in;
franta-hg@146
    49
			hasNext = verifyHeader();
franta-hg@146
    50
		}
franta-hg@146
    51
franta-hg@146
    52
		@Override
franta-hg@146
    53
		public boolean hasNext() throws BatchException {
franta-hg@146
    54
			return hasNext;
franta-hg@146
    55
		}
franta-hg@146
    56
franta-hg@146
    57
		@Override
franta-hg@146
    58
		public SQLCommand next() throws BatchException {
franta-hg@146
    59
			try {
franta-hg@146
    60
				String sql = readNextString();
franta-hg@146
    61
franta-hg@146
    62
				int paramCount = in.readInt();
franta-hg@146
    63
				List<Parameter> parameters = new ArrayList<>(paramCount);
franta-hg@146
    64
franta-hg@146
    65
				for (int i = 0; i < paramCount; i++) {
franta-hg@146
    66
					SQLType type = SQLType.valueOf(in.readInt());
franta-hg@146
    67
					String value = readNextString();
franta-hg@146
    68
					parameters.add(new Parameter(value, type));
franta-hg@146
    69
				}
franta-hg@146
    70
franta-hg@146
    71
				hasNext = verifyHeader();
franta-hg@146
    72
franta-hg@146
    73
				SQLCommand sqlCommand = new SQLCommandNumbered(sql, parameters);
franta-hg@146
    74
				return sqlCommand;
franta-hg@146
    75
			} catch (IOException e) {
franta-hg@146
    76
				throw new BatchException("Unable to read batch", e);
franta-hg@146
    77
			}
franta-hg@146
    78
		}
franta-hg@146
    79
franta-hg@146
    80
		private String readNextString() throws IOException {
franta-hg@146
    81
			byte[] buffer = new byte[in.readInt()];
franta-hg@146
    82
			in.read(buffer);
franta-hg@146
    83
			return new String(buffer, CHARSET);
franta-hg@146
    84
		}
franta-hg@146
    85
franta-hg@146
    86
		/**
franta-hg@146
    87
		 * @return true if correct batch header was found | false if EOF was found
franta-hg@146
    88
		 * @throws BatchException if unexpected data was found (not batch header nor EOF)
franta-hg@146
    89
		 */
franta-hg@146
    90
		private boolean verifyHeader() throws BatchException {
franta-hg@146
    91
			try {
franta-hg@146
    92
				byte[] buffer = new byte[BATCH_HEADER.length];
franta-hg@146
    93
				int bytesRead = in.read(buffer);
franta-hg@146
    94
franta-hg@146
    95
				if (bytesRead == BATCH_HEADER.length && Arrays.equals(buffer, BATCH_HEADER)) {
franta-hg@146
    96
					return true;
franta-hg@146
    97
				} else if (bytesRead == -1) {
franta-hg@146
    98
					return false;
franta-hg@146
    99
				} else {
franta-hg@146
   100
					throw new BatchException("This is not SQL-DK batch: " + toHex(buffer));
franta-hg@146
   101
				}
franta-hg@146
   102
			} catch (IOException e) {
franta-hg@146
   103
				throw new BatchException("Unable to read batch header", e);
franta-hg@146
   104
			}
franta-hg@146
   105
		}
franta-hg@146
   106
	}
franta-hg@146
   107
}