|
From: SVN by r. <sv...@ca...> - 2009-12-15 08:58:53
|
Author: roy
Date: 2009-12-15 09:58:40 +0100 (Tue, 15 Dec 2009)
New Revision: 433
Modified:
src/main/java/nl/improved/sqlclient/commands/ReadCommand.java
Log:
fix read command for very large files
(tried dump of 4.9G)
Modified: src/main/java/nl/improved/sqlclient/commands/ReadCommand.java
===================================================================
--- src/main/java/nl/improved/sqlclient/commands/ReadCommand.java 2009-12-08 10:18:57 UTC (rev 432)
+++ src/main/java/nl/improved/sqlclient/commands/ReadCommand.java 2009-12-15 08:58:40 UTC (rev 433)
@@ -1,5 +1,7 @@
package nl.improved.sqlclient.commands;
+import java.text.ParseException;
+import javax.xml.parsers.SAXParser;
import nl.improved.sqlclient.*;
import java.io.File;
import java.io.IOException;
@@ -9,12 +11,15 @@
import java.sql.SQLException;
import java.sql.Types;
import java.text.SimpleDateFormat;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.parsers.SAXParserFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
import sun.misc.BASE64Decoder;
/**
@@ -28,6 +33,7 @@
}
private String fileName;
+ private ReadCommandContentHandler contentHandler;
public ReadCommand(AbstractSQLShellWindow window) {
super(window);
@@ -45,109 +51,138 @@
} else {
dumpFileName = nextPart;
}
- int rowCount = 0;
try {
- File f = new File(AbstractSQLShellWindow.toFileName(dumpFileName + ".dmp"));
+ File f = new File(AbstractSQLShellWindow.toFileName(dumpFileName));
fileName = f.getAbsolutePath();
if (!f.exists() && !f.canRead()) {
- throw new IllegalStateException("Failed to read dump file: \'" + fileName + "\'");
+ f = new File(AbstractSQLShellWindow.toFileName(dumpFileName + ".dmp"));
+ fileName = f.getAbsolutePath();
+ if (!f.exists() && !f.canRead()) {
+ f = new File(AbstractSQLShellWindow.toFileName(dumpFileName + ".DMP"));
+ fileName = f.getAbsolutePath();
+ throw new IllegalStateException("Failed to read dump file: \'" + fileName + "\'");
+ }
}
- // Step 1: create a DocumentBuilderFactory
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- // Step 2: create a DocumentBuilder
- DocumentBuilder db = dbf.newDocumentBuilder();
- // Step 3: parse the input file to get a Document object
- Document doc = db.parse(new File(fileName));
- Element documentElement = doc.getDocumentElement();
- String tableName = documentElement.getAttribute("tablename");
- NodeList nodeList = documentElement.getElementsByTagName("row");
- String query = "insert into " + tableName + " (";
- String values = ") values (";
- Element n = (Element) nodeList.item(0);
- // row
- NodeList cols = n.getElementsByTagName("col");
- for (int colNr = 0; colNr < cols.getLength(); colNr++) {
- query += cols.item(colNr).getAttributes().getNamedItem("name").getNodeValue();
- values += "?";
- if (colNr + 1 < cols.getLength()) {
- query += ", ";
- values += ", ";
+
+ final SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);
+ final Connection c = DBConnector.getInstance().getConnection();
+ SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
+ XMLReader reader = parser.getXMLReader();
+ reader.setFeature("http://xml.org/sax/features/validation", false);
+ contentHandler = new ReadCommandContentHandler(fileName) {
+ final String NULL_DATE="null_date";
+ String query = null;
+ String values = ") values (";
+ List valuesList = new ArrayList();
+ PreparedStatement pstmt;
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+ if (qName.equals("dump")) {
+ query = "insert into " + atts.getValue("tablename") + " (";
+ }
+ super.startElement(uri, localName, qName, atts);
}
- }
- query = query + values + ")";
- Connection c = DBConnector.getInstance().getConnection();
- PreparedStatement pstmt = c.prepareStatement(query);
- SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);
- for (int nodeNr = 0; nodeNr < nodeList.getLength(); nodeNr++) {
- Element row = (Element) nodeList.item(nodeNr);
- // row
- NodeList columns = row.getElementsByTagName("col");
- for (int colNr = 0; colNr < columns.getLength(); colNr++) {
- Element column = (Element) columns.item(colNr);
- Node type = column.getAttributes().getNamedItem("type");
- if (type != null) {
- String typeString = type.getNodeValue();
+
+ @Override
+ public void handleElement(ElementInfo info, String content) throws SQLException, IOException {
+ if (info.name.equals("row")) {
+ if (!query.endsWith(")")) {
+ query = query + values + ")";
+ pstmt = c.prepareStatement(query);
+ }
+ for (int i = 0; i < valuesList.size() ; i++) {
+ Object o = valuesList.get(i);
+ if (o == NULL_DATE) {
+ pstmt.setDate(i+1, null);
+ } else {
+ pstmt.setObject(i+1, o);
+ }
+ }
+ // execute query...
+ pstmt.executeUpdate();
+ valuesList.clear();
+ rowCount++;
+ if (rowCount % 100000 == 0) {
+ if (autoCommit) {
+ pstmt.getConnection().commit();
+ output(Integer.toString(rowCount)+" rows comitted");
+ } else {
+ output(Integer.toString(rowCount)+" rows inserted");
+ }
+ }
+ }
+ if (info.name.equals("col")) {
+ if (!query.endsWith(")")) {
+ if (values.endsWith("?")) {
+ values+=",";
+ }
+ values += "?";
+ }
+ String typeString = info.atts.getValue("type");
if (typeString.equals("date")) {
- String nodeValue = column.getTextContent();
+ String nodeValue = content;
if (nodeValue == null || nodeValue.equals("")) {
- pstmt.setDate(colNr + 1, null);
+ valuesList.add(NULL_DATE);
} else {
- pstmt.setDate(colNr + 1, new Date(formatter.parse(nodeValue).getTime()));
+ try {
+ //pstmt.setDate(colNr + 1, new Date(formatter.parse(nodeValue).getTime()));
+ valuesList.add(new Date(formatter.parse(nodeValue).getTime()));
+ } catch (ParseException ex) {
+ throw new IOException("Failed to parse date :"+ nodeValue);
+ }
}
} else if (typeString.equals("binary")) {
- String nodeValue = column.getTextContent();
+ String nodeValue = content;
BASE64Decoder decoder = new BASE64Decoder();
byte[] value = decoder.decodeBuffer(nodeValue);
- pstmt.setBytes(colNr + 1, value);
+ valuesList.add(value);
} else {
- String nodeValue = column.getTextContent();
- int iType = Integer.parseInt(typeString);
- switch (iType) {
- case Types.INTEGER:
- case Types.SMALLINT:
- case Types.BIGINT:
- pstmt.setInt(colNr + 1, Integer.parseInt(nodeValue));
- break;
- case Types.DOUBLE:
- pstmt.setDouble(colNr + 1, Double.parseDouble(nodeValue));
- break;
- case Types.VARCHAR:
- case Types.CHAR:
- case Types.LONGNVARCHAR:
- case Types.NCHAR:
- case Types.NVARCHAR:
- pstmt.setString(colNr + 1, nodeValue);
- break;
- default:
- pstmt.setString(colNr + 1, nodeValue);
+ String nodeValue = content;
+ if (typeString.startsWith(".")) {
+ typeString = typeString.substring(1);
}
+ try {
+ int iType = Integer.parseInt(typeString);
+ switch (iType) {
+ case Types.INTEGER:
+ case Types.SMALLINT:
+ case Types.BIGINT:
+ valuesList.add(Integer.parseInt(nodeValue));
+ break;
+ case Types.DOUBLE:
+ valuesList.add(Double.parseDouble(nodeValue));
+ break;
+ case Types.VARCHAR:
+ case Types.CHAR:
+ case Types.LONGNVARCHAR:
+ case Types.NCHAR:
+ case Types.NVARCHAR:
+ valuesList.add(nodeValue);
+ break;
+ default:
+ valuesList.add(nodeValue);
+ }
+ } catch(Exception e) {
+ valuesList.add(nodeValue);
+ }
}
- } else {
- //debug(nodeNr +" ? "+column.getTextContent());
- pstmt.setString(colNr + 1, column.getTextContent());
}
}
- pstmt.executeUpdate();
- rowCount++;
- if (rowCount % 1000 == 0) {
- if (autoCommit) {
- pstmt.getConnection().commit();
- output(Integer.toString(rowCount)+" rows comitted");
- } else {
- output(Integer.toString(rowCount)+" rows inserted");
- }
- }
- }
- } catch (SQLException e) {
- throw new IllegalStateException("Failed to execute update query for dump(" + fileName + "): " + e.toString(), e);
- } catch (IOException e) {
- throw new IllegalStateException("Failed to read dump (" + fileName + "): " + e.toString(), e);
+ };
+ reader.setContentHandler(contentHandler);
+ //parser.parse(new File(fileName), new DefaultHandler());
+ parser.parse(new File(fileName), (DefaultHandler)null);
+ contentHandler = null;
+ return new SimpleCommandResult(true, "Read from " + fileName + " done. (" + contentHandler.rowCount + " rows imported)");
+ } catch (AbortException e) {
+ return new SimpleCommandResult(true, "Read from " + fileName + " aborted. (" + contentHandler.rowCount + " rows imported)");
} catch (Exception e) {
throw new IllegalStateException("Failed to read dump (" + fileName + "): " + e.toString(), e);
}
- return new SimpleCommandResult(true, "Read from " + fileName + " done. (" + rowCount + " rows imported)");
}
+
@Override
public CharSequence getCommandString() {
return "read";
@@ -172,11 +207,117 @@
@Override
public boolean abort() {
+ if (contentHandler != null) {
+ contentHandler.abort = true;
+ }
return false;
}
@Override
public boolean backgroundProcessSupported() {
- return false;
+ return true;
}
+
+ private static abstract class ReadCommandContentHandler implements ContentHandler {
+
+ int rowCount = 0;
+ private List<ElementInfo> nameTree = new ArrayList<ElementInfo>();
+ private StringBuffer content;
+ private boolean failed = false;
+ private final String fileName;
+ private boolean abort;
+
+ public ReadCommandContentHandler(String fileName) {
+ this.fileName = fileName;
+ }
+
+
+ public void setDocumentLocator(Locator locator) {
+ }
+
+ public void startDocument() throws SAXException {
+ nameTree.clear();
+ content = new StringBuffer();
+ }
+
+ public void endDocument() throws SAXException {
+ nameTree.clear();
+ }
+
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ }
+
+ public void endPrefixMapping(String prefix) throws SAXException {
+ }
+
+ public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+ nameTree.add(new ElementInfo(qName, atts));
+ if (abort) {
+ throw new AbortException();
+ }
+ }
+
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ if (nameTree.get(nameTree.size()-1).name.equals(qName)) {
+ try {
+ handleElement(nameTree.remove(nameTree.size() - 1), content.toString());
+ } catch (SQLException e) {
+ throw new IllegalStateException("Failed to execute update query for dump(" + fileName + "): " + e.toString(), e);
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to read dump (" + fileName + "): " + e.toString(), e);
+ }
+ content = new StringBuffer();
+ } else {
+ throw new IllegalStateException("Closing unopened element");
+ }
+ }
+
+ public abstract void handleElement(ElementInfo info, String content) throws SQLException, IOException;
+
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ content.append(ch, start, length);
+ }
+
+ public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
+ content.append(ch, start, length);
+ }
+
+ public void processingInstruction(String target, String data) throws SAXException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void skippedEntity(String name) throws SAXException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ }
+
+ private static class ElementInfo {
+ private final String name;
+ private final Attributes atts;
+
+ public ElementInfo(String name, Attributes atts) {
+ this.name = name;
+ this.atts = atts;
+ }
+ }
+
+ private static class AbortException extends RuntimeException {
+
+ }
+
+ public static void main(String[] args) throws Exception {
+ final String fileName = args[0];
+ SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
+ XMLReader reader = parser.getXMLReader();
+ reader.setFeature("http://xml.org/sax/features/validation", false);
+ reader.setContentHandler(new ReadCommandContentHandler(fileName) {
+ @Override
+ public void handleElement(ElementInfo info, String content) throws SQLException, IOException {
+ System.out.println(info.name);
+ }
+ });
+ //parser.parse(new File(fileName), new DefaultHandler());
+ parser.parse(new File(fileName), (DefaultHandler)null);
+ }
}
|