File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\util\ScriptReader.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.util;
8
9 import java.io.IOException;
10 import java.io.Reader;
11 import java.util.Arrays;
12 import org.h2.engine.Constants;
13 import org.h2.message.DbException;
14
15 /**
16 * This class can split SQL scripts to single SQL statements.
17 * Each SQL statement ends with the character ';', however it is ignored
18 * in comments and quotes.
19 */
20 public class ScriptReader {
21 private final Reader reader;
22 private char[] buffer;
23 private int bufferPos;
24 private int bufferStart = -1;
25 private int bufferEnd;
26 private boolean endOfFile;
27 private boolean insideRemark;
28 private boolean blockRemark;
29 private boolean skipRemarks;
30 private int remarkStart;
31
32 /**
33 * Create a new SQL script reader from the given reader
34 *
35 * @param reader the reader
36 */
37 public ScriptReader(Reader reader) {
38 this.reader = reader;
39 buffer = new char[Constants.IO_BUFFER_SIZE * 2];
40 }
41
42 /**
43 * Close the underlying reader.
44 */
45 public void close() {
46 try {
47 reader.close();
48 } catch (IOException e) {
49 throw DbException.convertIOException(e, null);
50 }
51 }
52
53 /**
54 * Read a statement from the reader. This method returns null if the end has
55 * been reached.
56 *
57 * @return the SQL statement or null
58 */
59 public String readStatement() {
60 if (endOfFile) {
61 return null;
62 }
63 try {
64 return readStatementLoop();
65 } catch (IOException e) {
66 throw DbException.convertIOException(e, null);
67 }
68 }
69
70 private String readStatementLoop() throws IOException {
71 bufferStart = bufferPos;
72 int c = read();
73 while (true) {
74 if (c < 0) {
75 endOfFile = true;
76 if (bufferPos - 1 == bufferStart) {
77 return null;
78 }
79 break;
80 } else if (c == ';') {
81 break;
82 }
83 switch (c) {
84 case '$': {
85 c = read();
86 if (c == '$' && (bufferPos - bufferStart < 3 || buffer[bufferPos - 3] <= ' ')) {
87 // dollar quoted string
88 while (true) {
89 c = read();
90 if (c < 0) {
91 break;
92 }
93 if (c == '$') {
94 c = read();
95 if (c < 0) {
96 break;
97 }
98 if (c == '$') {
99 break;
100 }
101 }
102 }
103 c = read();
104 }
105 break;
106 }
107 case '\'':
108 while (true) {
109 c = read();
110 if (c < 0) {
111 break;
112 }
113 if (c == '\'') {
114 break;
115 }
116 }
117 c = read();
118 break;
119 case '"':
120 while (true) {
121 c = read();
122 if (c < 0) {
123 break;
124 }
125 if (c == '\"') {
126 break;
127 }
128 }
129 c = read();
130 break;
131 case '/': {
132 c = read();
133 if (c == '*') {
134 // block comment
135 startRemark(false);
136 while (true) {
137 c = read();
138 if (c < 0) {
139 break;
140 }
141 if (c == '*') {
142 c = read();
143 if (c < 0) {
144 clearRemark();
145 break;
146 }
147 if (c == '/') {
148 endRemark();
149 break;
150 }
151 }
152 }
153 c = read();
154 } else if (c == '/') {
155 // single line comment
156 startRemark(false);
157 while (true) {
158 c = read();
159 if (c < 0) {
160 clearRemark();
161 break;
162 }
163 if (c == '\r' || c == '\n') {
164 endRemark();
165 break;
166 }
167 }
168 c = read();
169 }
170 break;
171 }
172 case '-': {
173 c = read();
174 if (c == '-') {
175 // single line comment
176 startRemark(false);
177 while (true) {
178 c = read();
179 if (c < 0) {
180 clearRemark();
181 break;
182 }
183 if (c == '\r' || c == '\n') {
184 endRemark();
185 break;
186 }
187 }
188 c = read();
189 }
190 break;
191 }
192 default: {
193 c = read();
194 }
195 }
196 }
197 return new String(buffer, bufferStart, bufferPos - 1 - bufferStart);
198 }
199
200 private void startRemark(boolean block) {
201 blockRemark = block;
202 remarkStart = bufferPos - 2;
203 insideRemark = true;
204 }
205
206 private void endRemark() {
207 clearRemark();
208 insideRemark = false;
209 }
210
211 private void clearRemark() {
212 if (skipRemarks) {
213 Arrays.fill(buffer, remarkStart, bufferPos, ' ');
214 }
215 }
216
217 private int read() throws IOException {
218 if (bufferPos >= bufferEnd) {
219 return readBuffer();
220 }
221 return buffer[bufferPos++];
222 }
223
224 private int readBuffer() throws IOException {
225 if (endOfFile) {
226 return -1;
227 }
228 int keep = bufferPos - bufferStart;
229 if (keep > 0) {
230 char[] src = buffer;
231 if (keep + Constants.IO_BUFFER_SIZE > src.length) {
232 buffer = new char[src.length * 2];
233 }
234 System.arraycopy(src, bufferStart, buffer, 0, keep);
235 }
236 remarkStart -= bufferStart;
237 bufferStart = 0;
238 bufferPos = keep;
239 int len = reader.read(buffer, keep, Constants.IO_BUFFER_SIZE);
240 if (len == -1) {
241 // ensure bufferPos > bufferEnd
242 bufferEnd = -1024;
243 endOfFile = true;
244 // ensure the right number of characters are read
245 // in case the input buffer is still used
246 bufferPos++;
247 return -1;
248 }
249 bufferEnd = keep + len;
250 return buffer[bufferPos++];
251 }
252
253 /**
254 * Check if this is the last statement, and if the single line or block
255 * comment is not finished yet.
256 *
257 * @return true if the current position is inside a remark
258 */
259 public boolean isInsideRemark() {
260 return insideRemark;
261 }
262
263 /**
264 * If currently inside a remark, this method tells if it is a block comment
265 * (true) or single line comment (false)
266 *
267 * @return true if inside a block comment
268 */
269 public boolean isBlockRemark() {
270 return blockRemark;
271 }
272
273 /**
274 * If comments should be skipped completely by this reader.
275 *
276 * @param skipRemarks true if comments should be skipped
277 */
278 public void setSkipRemarks(boolean skipRemarks) {
279 this.skipRemarks = skipRemarks;
280 }
281
282 }
283