001: /* Copyright (c) 2001-2005, The HSQL Development Group
002: * All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * Redistributions of source code must retain the above copyright notice, this
008: * list of conditions and the following disclaimer.
009: *
010: * Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * Neither the name of the HSQL Development Group nor the names of its
015: * contributors may be used to endorse or promote products derived from this
016: * software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
022: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
026: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package org.hsqldb.scriptio;
032:
033: import java.io.IOException;
034:
035: import org.hsqldb.Database;
036: import org.hsqldb.HsqlException;
037: import org.hsqldb.HsqlNameManager;
038: import org.hsqldb.HsqlNameManager.HsqlName;
039: import org.hsqldb.NumberSequence;
040: import org.hsqldb.Session;
041: import org.hsqldb.Table;
042: import org.hsqldb.rowio.RowOutputTextLog;
043:
044: /**
045: * Handles all scripting and logging operations. A script consists of two blocks:<p>
046: *
047: * DDL: SQL statements for table and user definitions
048: * DATA: INSERT statements for memory tables
049: *
050: * This happens as part of the CHECKPOINT and SHUTDOWN COMPACT
051: * process. In this case, the
052: * DATA block contains the CACHED table data as well.<p>
053: *
054: * A related use for this class is for saving a current snapshot of the
055: * database data to a user-defined file with the SCRIPT command
056: *
057: * A log consists of SQL statements of different types. Each statement is
058: * encoded as ASCII and saved.
059: *
060: *
061: * @author fredt@users
062: * @version 1.8.0
063: * @since 1.7.2
064: */
065: public class ScriptWriterText extends ScriptWriterBase {
066:
067: RowOutputTextLog rowOut;
068:
069: // todo - perhaps move this global into a lib utility class
070: public static final byte[] BYTES_LINE_SEP;
071:
072: static {
073: String sLineSep = System.getProperty("line.separator", "\n");
074:
075: BYTES_LINE_SEP = sLineSep.getBytes();
076: }
077:
078: static final byte[] BYTES_COMMIT = "COMMIT".getBytes();
079: static final byte[] BYTES_INSERT_INTO = "INSERT INTO ".getBytes();
080: static final byte[] BYTES_VALUES = " VALUES(".getBytes();
081: static final byte[] BYTES_TERM = ")".getBytes();
082: static final byte[] BYTES_DELETE_FROM = "DELETE FROM ".getBytes();
083: static final byte[] BYTES_WHERE = " WHERE ".getBytes();
084: static final byte[] BYTES_SEQUENCE = "ALTER SEQUENCE ".getBytes();
085: static final byte[] BYTES_SEQUENCE_MID = " RESTART WITH "
086: .getBytes();
087: static final byte[] BYTES_C_ID_INIT = "/*C".getBytes();
088: static final byte[] BYTES_C_ID_TERM = "*/".getBytes();
089: static final byte[] BYTES_SCHEMA = "SET SCHEMA ".getBytes();
090:
091: ScriptWriterText() {
092: }
093:
094: public ScriptWriterText(Database db, String file,
095: boolean includeCachedData, boolean newFile, boolean isDump)
096: throws HsqlException {
097: super (db, file, includeCachedData, newFile, isDump);
098: }
099:
100: protected void initBuffers() {
101: rowOut = new RowOutputTextLog();
102: }
103:
104: protected void writeDataTerm() throws IOException {
105: }
106:
107: protected void addSessionId(Session session) throws IOException {
108:
109: if (session == null) {
110: return;
111: }
112:
113: if (session != currentSession) {
114: rowOut.write(BYTES_C_ID_INIT);
115: rowOut.writeIntData(session.getId());
116: rowOut.write(BYTES_C_ID_TERM);
117:
118: currentSession = session;
119: }
120:
121: if (schemaToLog != session.loggedSchema) {
122: writeSchemaStatement(schemaToLog);
123:
124: session.loggedSchema = schemaToLog;
125: }
126: }
127:
128: private void writeSchemaStatement(HsqlName schema) {
129:
130: rowOut.write(BYTES_SCHEMA);
131: rowOut.writeString(schema.statementName);
132: rowOut.write(BYTES_LINE_SEP);
133: }
134:
135: public void writeLogStatement(Session session, String s)
136: throws IOException, HsqlException {
137:
138: schemaToLog = session.currentSchema;
139: busyWriting = true;
140:
141: rowOut.reset();
142: addSessionId(session);
143: rowOut.writeString(s);
144: rowOut.write(BYTES_LINE_SEP);
145: fileStreamOut.write(rowOut.getBuffer(), 0, rowOut.size());
146:
147: byteCount += rowOut.size();
148: needsSync = true;
149: busyWriting = false;
150:
151: if (forceSync || writeDelay == 0) {
152: sync();
153: }
154: }
155:
156: protected void writeRow(Session session, Table table, Object[] data)
157: throws HsqlException, IOException {
158:
159: busyWriting = true;
160:
161: rowOut.reset();
162: ((RowOutputTextLog) rowOut)
163: .setMode(RowOutputTextLog.MODE_INSERT);
164: addSessionId(session);
165: rowOut.write(BYTES_INSERT_INTO);
166: rowOut.writeString(table.getName().statementName);
167: rowOut.write(BYTES_VALUES);
168: rowOut.writeData(data, table);
169: rowOut.write(BYTES_TERM);
170: rowOut.write(BYTES_LINE_SEP);
171: fileStreamOut.write(rowOut.getBuffer(), 0, rowOut.size());
172:
173: byteCount += rowOut.size();
174: needsSync |= session.isAutoCommit();
175: busyWriting = false;
176:
177: if (forceSync || writeDelay == 0) {
178: sync();
179: }
180: }
181:
182: protected void writeTableInit(Table t) throws HsqlException,
183: IOException {
184:
185: if (t.isEmpty(currentSession)) {
186: return;
187: }
188:
189: if (schemaToLog == currentSession.loggedSchema) {
190: return;
191: }
192:
193: rowOut.reset();
194: writeSchemaStatement(t.getName().schema);
195: fileStreamOut.write(rowOut.getBuffer(), 0, rowOut.size());
196:
197: currentSession.loggedSchema = schemaToLog;
198: }
199:
200: public void writeInsertStatement(Session session, Table table,
201: Object[] data) throws HsqlException, IOException {
202:
203: schemaToLog = table.getName().schema;
204:
205: writeRow(session, table, data);
206: }
207:
208: public void writeDeleteStatement(Session session, Table table,
209: Object[] data) throws HsqlException, IOException {
210:
211: schemaToLog = table.getName().schema;
212: busyWriting = true;
213:
214: rowOut.reset();
215: ((RowOutputTextLog) rowOut)
216: .setMode(RowOutputTextLog.MODE_DELETE);
217: addSessionId(session);
218: rowOut.write(BYTES_DELETE_FROM);
219: rowOut.writeString(table.getName().statementName);
220: rowOut.write(BYTES_WHERE);
221: rowOut.writeData(table.getColumnCount(),
222: table.getColumnTypes(), data, table.columnList, table
223: .getPrimaryKey());
224: rowOut.write(BYTES_LINE_SEP);
225: fileStreamOut.write(rowOut.getBuffer(), 0, rowOut.size());
226:
227: byteCount += rowOut.size();
228: needsSync |= session.isAutoCommit();
229: busyWriting = false;
230:
231: if (forceSync || writeDelay == 0) {
232: sync();
233: }
234: }
235:
236: public void writeSequenceStatement(Session session,
237: NumberSequence seq) throws HsqlException, IOException {
238:
239: schemaToLog = seq.getName().schema;
240: busyWriting = true;
241:
242: rowOut.reset();
243: addSessionId(session);
244: rowOut.write(BYTES_SEQUENCE);
245: rowOut.writeString(seq.getName().statementName);
246: rowOut.write(BYTES_SEQUENCE_MID);
247: rowOut.writeLongData(seq.peek());
248: rowOut.write(BYTES_LINE_SEP);
249: fileStreamOut.write(rowOut.getBuffer(), 0, rowOut.size());
250:
251: byteCount += rowOut.size();
252: needsSync = true;
253: busyWriting = false;
254:
255: if (forceSync || writeDelay == 0) {
256: sync();
257: }
258: }
259:
260: public void writeCommitStatement(Session session)
261: throws HsqlException, IOException {
262:
263: busyWriting = true;
264:
265: rowOut.reset();
266: addSessionId(session);
267: rowOut.write(BYTES_COMMIT);
268: rowOut.write(BYTES_LINE_SEP);
269: fileStreamOut.write(rowOut.getBuffer(), 0, rowOut.size());
270:
271: byteCount += rowOut.size();
272: needsSync = true;
273: busyWriting = false;
274:
275: if (forceSync || writeDelay == 0) {
276: sync();
277: }
278: }
279:
280: protected void finalize() {
281: sync();
282: }
283: }
|