/* Copyright (c) 2001-2008, The HSQL Development Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.hsqldb.util;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.Vector;
/**
* @author Nicolas BAZIN, INGENICO
* @version 1.7.0
*/
class TransferSQLText extends DataAccessPoint {
String sFileName = null;
BufferedWriter WTextWrite = null;
BufferedReader WTextRead = null;
protected boolean StructureAlreadyParsed = false;
Hashtable DbStmts = null;
protected JDBCTypes JDBCT = null;
TransferSQLText(String _FileName,
Traceable t) throws DataAccessPointException {
super(t);
sFileName = _FileName;
JDBCT = new JDBCTypes();
if (sFileName == null) {
throw new DataAccessPointException("File name not initialized");
}
}
boolean execute(String statement) throws DataAccessPointException {
if (WTextWrite == null) {
try {
WTextWrite = new BufferedWriter(new FileWriter(sFileName));
} catch (IOException e) {
throw new DataAccessPointException(e.getMessage());
}
}
try {
WTextWrite.write(statement + "\n");
WTextWrite.flush();
} catch (IOException e) {
throw new DataAccessPointException(e.getMessage());
}
return true;
}
void putData(String statement, TransferResultSet r,
int iMaxRows) throws DataAccessPointException {
int i = 0;
if (r == null) {
return;
}
if (WTextWrite == null) {
try {
WTextWrite = new BufferedWriter(new FileWriter(sFileName));
} catch (IOException e) {
throw new DataAccessPointException(e.getMessage());
}
}
try {
while (r.next()) {
if (i == 0) {
WTextWrite.write(statement + "\n");
WTextWrite.flush();
}
transferRow(r);
if (iMaxRows != 0 && i == iMaxRows) {
break;
}
i++;
if (iMaxRows != 0 || i % 100 == 0) {
tracer.trace("Transfered " + i + " rows");
}
}
} catch (Exception e) {
throw new DataAccessPointException(e.getMessage());
} finally {
try {
if (i > 0) {
WTextWrite.write("\tNumber of Rows=" + i + "\n\n");
WTextWrite.flush();
}
} catch (IOException e) {
throw new DataAccessPointException(e.getMessage());
}
}
}
void close() throws DataAccessPointException {
if (WTextWrite != null) {
try {
WTextWrite.flush();
WTextWrite.close();
} catch (IOException e) {}
}
}
/**
* Method declaration
*
*
* @param type
* @param r
* @param p
*
* @throws SQLException
*/
private void transferRow(TransferResultSet r) throws Exception {
String sLast = "";
int len = r.getColumnCount();
if (WTextWrite == null) {
try {
WTextWrite = new BufferedWriter(new FileWriter(sFileName));
} catch (IOException e) {
throw new DataAccessPointException(e.getMessage());
}
}
for (int i = 0; i < len; i++) {
int t = r.getColumnType(i + 1);
sLast = "column=" + r.getColumnName(i + 1) + " datatype="
+ (String) helper.getSupportedTypes().get(new Integer(t));
Object o = r.getObject(i + 1);
if (o == null) {
sLast += " value=<null>";
} else {
o = helper.convertColumnValue(o, i + 1, t);
sLast += " value=\'" + o.toString() + "\'";
}
WTextWrite.write("\t" + sLast + "\n");
WTextWrite.flush();
}
WTextWrite.write("\n");
WTextWrite.flush();
sLast = "";
}
class ColumnDef {
String columnName;
String columnType;
String options;
int start;
int len;
public ColumnDef() {
columnName = "";
columnType = "";
options = "";
start = 0;
len = 0;
}
}
ColumnDef getColumnDef(String ColumnsDesc, int curPos) {
int nextPos = 0;
ColumnDef columnDef = new TransferSQLText.ColumnDef();
columnDef.start = curPos;
if ((ColumnsDesc == null) || (ColumnsDesc.length() == 0)
|| (curPos >= ColumnsDesc.length())) {
return new TransferSQLText.ColumnDef();
}
String stbuff = ColumnsDesc.substring(curPos);
try {
int i = 0;
for (; i < stbuff.length(); i++) {
int c = stbuff.charAt(i);
if (c == ',' || c == ' ' || c == ')' || c == ';') {
continue;
} else {
break;
}
}
if (i == stbuff.length()) {
return new TransferSQLText.ColumnDef();
}
columnDef.len += i;
stbuff = stbuff.substring(i);
while (stbuff.charAt(nextPos) != ' ') {
nextPos++;
}
columnDef.columnName = stbuff.substring(0, nextPos);
stbuff = stbuff.substring(nextPos);
columnDef.len += nextPos;
nextPos = 0;
if (!columnDef.columnName.toUpperCase().equals("CONSTRAINT")) {
i = 0;
for (; i < stbuff.length() && stbuff.charAt(i) == ' '; i++) {}
stbuff = stbuff.substring(i);
columnDef.len += i;
while ((stbuff.charAt(nextPos) != '(')
&& (stbuff.charAt(nextPos) != ',')
&& (stbuff.charAt(nextPos) != ')')
&& (stbuff.charAt(nextPos) != ';')
&& (stbuff.charAt(nextPos) != ' ')) {
nextPos++;
}
columnDef.columnType = stbuff.substring(0,
nextPos).toUpperCase();
stbuff = stbuff.substring(nextPos);
columnDef.len += nextPos;
nextPos = 0;
}
while ((stbuff.charAt(nextPos) != ',')
&& (stbuff.charAt(nextPos) != ';')
&& (nextPos < stbuff.length())
&& (stbuff.charAt(nextPos) != ')')) {
if (stbuff.charAt(nextPos) == '(') {
while (stbuff.charAt(nextPos) != ')') {
nextPos++;
}
}
nextPos++;
}
columnDef.options = stbuff.substring(0, nextPos);
columnDef.len += nextPos;
} catch (Exception e) {
columnDef = new TransferSQLText.ColumnDef();
}
return columnDef;
}
String translateTypes(String CreateLine, TransferTable TTable,
DataAccessPoint Dest)
throws DataAccessPointException {
String translatedLine = "";
JDBCTypes JDBCT = new JDBCTypes();
int currentPos = 0;
String columnName = "";
String columnType = "";
int colnum = 0;
ColumnDef cDef;
currentPos = CreateLine.indexOf('(') + 1;
translatedLine = CreateLine.substring(0, currentPos);
do {
cDef = getColumnDef(CreateLine, currentPos);
if (cDef.len == 0) {
break;
}
columnName = cDef.columnName;
columnType = cDef.columnType;
if (columnName.toUpperCase().indexOf("CONSTRAINT") >= 0) {
translatedLine +=
CreateLine.substring(currentPos, currentPos + cDef.len)
+ ",";
currentPos += cDef.len + 1;
colnum++;
continue;
}
columnName = Dest.helper.formatIdentifier(columnName) + " ";
try {
Integer inttype = new Integer(
Dest.helper.convertToType(JDBCT.toInt(columnType)));
columnType = (String) TTable.hTypes.get(inttype);
} catch (Exception JDBCtypeEx) {}
if (cDef.options != null) {
columnType += cDef.options;
}
try {
columnType = Dest.helper.fixupColumnDefWrite(TTable, null,
columnType, null, colnum);
} catch (SQLException SQLe) {
return CreateLine;
}
translatedLine += columnName + " " + columnType + ",";
currentPos += cDef.len + 1;
colnum++;
} while (true);
return translatedLine.substring(0, translatedLine.length() - 1)
+ ");";
}
void parseFileForTables() throws DataAccessPointException {
StringTokenizer Tokenizer;
if (WTextRead == null) {
try {
WTextRead = new BufferedReader(new FileReader(sFileName));
} catch (IOException e) {
throw new DataAccessPointException(e.getMessage());
}
}
String currentLine = "";
String Token = "";
String name = "";
TransferTable relatedTable = null;
try {
while ((currentLine = WTextRead.readLine()) != null) {
currentLine = currentLine.trim() + ";";
Tokenizer = new StringTokenizer(currentLine);
try {
Token = Tokenizer.nextToken();
} catch (NoSuchElementException NSE) {
continue;
}
if (Token == null) {
continue;
}
if (!Token.toUpperCase().equals("CREATE")) {
continue;
}
Token = Tokenizer.nextToken().toUpperCase();
if (Token.equals("TABLE") || Token.equals("VIEW")) {
try {
name = Tokenizer.nextToken(" (;");
relatedTable = new TransferTable(this, name, "",
Token, tracer);
relatedTable.Stmts.bCreate = false;
relatedTable.Stmts.bDelete = false;
relatedTable.Stmts.bDrop = false;
relatedTable.Stmts.bCreateIndex = false;
relatedTable.Stmts.bDropIndex = false;
relatedTable.Stmts.bInsert = false;
relatedTable.Stmts.bAlter = false;
DbStmts.put(relatedTable.Stmts.sSourceTable,
relatedTable);
} catch (NoSuchElementException NSE) {
continue;
}
}
}
} catch (Exception IOe) {
throw new DataAccessPointException(IOe.getMessage());
}
}
void parseFileForTheRest(TransferTable TTable,
DataAccessPoint Dest)
throws DataAccessPointException {
StringTokenizer Tokenizer;
StructureAlreadyParsed = true;
if (WTextRead == null) {
try {
WTextRead = new BufferedReader(new FileReader(sFileName));
} catch (IOException e) {
throw new DataAccessPointException(e.getMessage());
}
}
String currentLine = "";
String Token = "";
String name = "";
TransferTable relatedTable = null;
try {
while ((currentLine = WTextRead.readLine()) != null) {
currentLine = currentLine.trim() + ";";
Tokenizer = new StringTokenizer(currentLine);
try {
Token = Tokenizer.nextToken();
} catch (NoSuchElementException NSE) {
continue;
}
if (Token == null) {
continue;
}
if (Token.toUpperCase().equals("INSERT")) {
try {
if (!Tokenizer.nextToken().toUpperCase().equals(
"INTO")) {
throw new DataAccessPointException(
"Error in INSERT statement: no INTO found");
}
Token = Tokenizer.nextToken();
if ((relatedTable =
(TransferTable) DbStmts.get(Token)) != null) {
relatedTable.Stmts.bDelete = true;
relatedTable.Stmts.bInsert = true;
relatedTable.Stmts.sDestInsert = currentLine;
relatedTable.Stmts.sDestDelete =
"DELETE FROM "
+ relatedTable.Stmts.sSourceTable + ";";
}
continue;
} catch (NoSuchElementException NSE) {
continue;
}
} else if (Token.toUpperCase().equals("ALTER")) {
try {
if (!Tokenizer.nextToken().toUpperCase().equals(
"TABLE")) {
continue;
}
name = Tokenizer.nextToken();
Token = Tokenizer.nextToken().toUpperCase();
if (!Token.equals("ADD")) {
continue;
}
do {
Token = Tokenizer.nextToken().toUpperCase();
} while (!Token.equals("CONSTRAINT"));
if ((relatedTable = (TransferTable) DbStmts.get(name))
!= null) {
if (relatedTable.Stmts.sDestAlter == null) {
relatedTable.Stmts.sDestAlter = "";
}
relatedTable.Stmts.bAlter = true;
relatedTable.Stmts.sDestAlter += currentLine;
} else {
throw new DataAccessPointException(
"table not found");
}
Token = Tokenizer.nextToken();
if (relatedTable.Stmts.sDestDrop == null) {
relatedTable.Stmts.sDestDrop = "";
}
relatedTable.Stmts.bDrop = true;
relatedTable.Stmts.sDestDrop =
"ALTER TABLE " + name + " DROP CONSTRAINT "
+ Token + ";" + relatedTable.Stmts.sDestDrop;
continue;
} catch (NoSuchElementException NSE) {
continue;
}
} else if (!Token.toUpperCase().equals("CREATE")) {
continue;
}
Token = Tokenizer.nextToken().toUpperCase();
if (Token.equals("TABLE") || Token.equals("VIEW")) {
try {
name = Tokenizer.nextToken(" (;");
if (!DbStmts.containsKey(name)) {
throw new DataAccessPointException(
"error: index is created before the table");
}
relatedTable = (TransferTable) DbStmts.get(name);
relatedTable.Stmts.bCreate = true;
relatedTable.Stmts.bDrop = true;
// relatedTable.Stmts.sDestCreate = currentLine;
relatedTable.Stmts.sDestCreate =
translateTypes(currentLine, TTable, Dest);
relatedTable.Stmts.sDestDrop =
"DROP " + relatedTable.Stmts.sType + " " + name
+ ";";
DbStmts.put(relatedTable.Stmts.sSourceTable,
relatedTable);
} catch (NoSuchElementException NSE) {
continue;
}
}
if (Token.equals("INDEX") || Token.equals("UNIQUE")) {
try {
while ((Token =
Tokenizer.nextToken()).toUpperCase().equals(
"INDEX")) {
;
}
String IndexdropCommand = "DROP INDEX " + Token
+ " ;";
while ((Token = Tokenizer.nextToken(
" (")).toUpperCase().equals("ON")) {
;
}
name = Token;
if (!DbStmts.containsKey(Token)) {
throw new DataAccessPointException(
"error: index is created before the table");
}
relatedTable = (TransferTable) DbStmts.get(Token);
if (relatedTable.Stmts.sDestCreateIndex == null) {
relatedTable.Stmts.sDestCreateIndex = "";
}
if (relatedTable.Stmts.sDestDropIndex == null) {
relatedTable.Stmts.sDestDropIndex = "";
}
relatedTable.Stmts.bCreateIndex = true;
relatedTable.Stmts.bDropIndex = true;
relatedTable.Stmts.sDestCreateIndex += currentLine;
relatedTable.Stmts.sDestDropIndex += IndexdropCommand;
} catch (NoSuchElementException NSE) {
continue;
}
}
}
} catch (IOException IOe) {
throw new DataAccessPointException(IOe.getMessage());
}
}
Vector getTables(String sCatalog,
String[] sSchemas) throws DataAccessPointException {
Vector AllTables = new Vector();
if (DbStmts == null) {
DbStmts = new Hashtable();
}
if (WTextRead != null) {
try {
WTextRead.close();
WTextRead = null;
} catch (IOException e) {}
}
this.parseFileForTables();
StructureAlreadyParsed = false;
Enumeration e = DbStmts.elements();
while (e.hasMoreElements()) {
AllTables.addElement(e.nextElement());
}
return AllTables;
}
void getTableStructure(TransferTable TTable,
DataAccessPoint Dest)
throws DataAccessPointException {
if (!StructureAlreadyParsed) {
if (WTextRead != null) {
try {
WTextRead.close();
WTextRead = null;
} catch (IOException e) {}
}
this.parseFileForTheRest(TTable, Dest);
}
}
TransferResultSet getData(String statement)
throws DataAccessPointException {
StringTokenizer Tokenizer;
String tableName = "";
try {
Tokenizer = new StringTokenizer(statement);
while (!Tokenizer.nextToken().toUpperCase().equals("FROM")) {
;
}
tableName = Tokenizer.nextToken(" ;");
} catch (NoSuchElementException NSE) {
throw new DataAccessPointException(
"Table name not found in statement: " + statement);
}
if (WTextRead != null) {
try {
WTextRead.close();
WTextRead = null;
} catch (IOException e) {}
}
return (this.parseFileForData(tableName));
}
TransferResultSet parseFileForData(String tableName)
throws DataAccessPointException {
TransferResultSet trsData = new TransferResultSet();
StringTokenizer Tokenizer;
if (WTextRead == null) {
try {
WTextRead = new BufferedReader(new FileReader(sFileName));
} catch (IOException e) {
throw new DataAccessPointException(e.getMessage());
}
}
String currentLine = "";
String Token;
try {
while ((currentLine = WTextRead.readLine()) != null) {
currentLine = currentLine.trim() + ";";
Tokenizer = new StringTokenizer(currentLine);
try {
Token = Tokenizer.nextToken();
} catch (NoSuchElementException NSE) {
continue;
}
if (Token == null) {
continue;
}
if (!Token.toUpperCase().equals("INSERT")) {
continue;
}
try {
if (!Tokenizer.nextToken().toUpperCase().equals("INTO")) {
throw new DataAccessPointException(
"Error in INSERT statement: no INTO found");
}
Token = Tokenizer.nextToken();
if (!Token.equals(tableName)) {
continue;
}
int iParsedRows = 0;
Vector vColumnNames = new Vector();
Vector vColumnValues = new Vector();
Vector vColumnTypes = new Vector();
while ((currentLine = WTextRead.readLine()) != null) {
currentLine = currentLine.trim();
boolean newLine = (currentLine.length() == 0);
if (newLine) {
int iColumnNb = 0;
iParsedRows++;
iColumnNb = vColumnNames.size();
String[] Names = new String[iColumnNb + 1];
int[] Types = new int[iColumnNb + 1];
Object[] Values = new Object[iColumnNb + 1];
for (int Idx = 0; Idx < iColumnNb; Idx++) {
Names[Idx + 1] =
(String) vColumnNames.elementAt(Idx);
Types[Idx + 1] =
((Integer) vColumnTypes.elementAt(
Idx)).intValue();
Values[Idx + 1] =
vColumnValues.elementAt(Idx);
}
try {
trsData.addRow(Names, Types, Values,
iColumnNb);
} catch (Exception e) {
throw new DataAccessPointException(
e.getMessage());
}
iColumnNb = 0;
vColumnNames.removeAllElements();
vColumnValues.removeAllElements();
vColumnTypes.removeAllElements();
continue;
}
Tokenizer = new StringTokenizer(currentLine);
Token = Tokenizer.nextToken("=");
if (Token.equals("Number of Rows")) {
int iNbRows =
Integer.parseInt(Tokenizer.nextToken());
if (iNbRows != iParsedRows) {
throw new DataAccessPointException(
"Number of parsed rows (" + iParsedRows
+ ") is different from the expected ("
+ iNbRows + ")");
}
return trsData;
}
if (Token.equals("column")) {
Token = Tokenizer.nextToken(" =");
vColumnNames.addElement(Token);
}
Token = Tokenizer.nextToken(" =");
if (Token.equals("datatype")) {
int iType;
Token = Tokenizer.nextToken(" =");
try {
iType = JDBCT.toInt(Token.toUpperCase());
} catch (Exception e) {
throw new DataAccessPointException(
"Unknown type: " + Token);
}
vColumnTypes.addElement(new Integer(iType));
}
Token = Tokenizer.nextToken(" =");
if (Token.equals("value")) {
int iStart = currentLine.indexOf("value=") + 6;
String sValue =
currentLine.substring(iStart).trim();
if (sValue.indexOf("<null>") >= 0) {
vColumnValues.addElement(null);
} else {
int i = sValue.indexOf('\'') + 1;
String sbToken = sValue.substring(i);
i = sbToken.lastIndexOf('\'');
sbToken = sbToken.substring(0, i);
Token = sbToken;
vColumnValues.addElement(Token);
}
}
}
} catch (IndexOutOfBoundsException IOBe) {
continue;
}
}
} catch (IOException IOe) {
throw new DataAccessPointException(IOe.getMessage());
}
return trsData;
}
}