/* Copyright (c) 2001-2011, 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;
}
}