* Support binary database column mapping, fix http://helma.org/bugs/show_bug.cgi?id=498

* Some code cleanup and minor rewrites.
This commit is contained in:
hns 2007-02-15 15:08:43 +00:00
parent c0118398bb
commit 04a9ce2d3a
2 changed files with 65 additions and 50 deletions

View file

@ -21,10 +21,7 @@ import helma.framework.core.RequestEvaluator;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.objectmodel.dom.XmlDatabase; import helma.objectmodel.dom.XmlDatabase;
import java.io.IOException; import java.io.*;
import java.io.Reader;
import java.io.StringReader;
import java.io.File;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.*; import java.sql.*;
import java.util.*; import java.util.*;
@ -493,29 +490,29 @@ public final class NodeManager {
long logTimeStart = logSql ? System.currentTimeMillis() : 0; long logTimeStart = logSql ? System.currentTimeMillis() : 0;
try { try {
int stmtNumber = 1; int columnNumber = 1;
for (int i = 0; i < columns.length; i++) { for (int i = 0; i < columns.length; i++) {
DbColumn col = columns[i]; DbColumn col = columns[i];
if (!col.isMapped()) if (!col.isMapped())
continue; continue;
if (col.isIdField()) { if (col.isIdField()) {
setStatementValue(stmt, stmtNumber, node.getID(), col); setStatementValue(stmt, columnNumber, node.getID(), col);
} else if (col.isPrototypeField()) { } else if (col.isPrototypeField()) {
setStatementValue(stmt, stmtNumber, dbm.getExtensionId(), col); setStatementValue(stmt, columnNumber, dbm.getExtensionId(), col);
} else { } else {
Relation rel = col.getRelation(); Relation rel = col.getRelation();
Property p = rel == null ? null : node.getProperty(rel.getPropName()); Property p = rel == null ? null : node.getProperty(rel.getPropName());
if (p != null) { if (p != null) {
setStatementValue(stmt, stmtNumber, p, col.getType()); setStatementValue(stmt, columnNumber, p, col.getType());
} else if (col.isNameField()) { } else if (col.isNameField()) {
stmt.setString(stmtNumber, node.getName()); stmt.setString(columnNumber, node.getName());
} else { } else {
stmt.setNull(stmtNumber, col.getType()); stmt.setNull(columnNumber, col.getType());
} }
} }
stmtNumber += 1; columnNumber += 1;
} }
stmt.executeUpdate(); stmt.executeUpdate();
@ -572,7 +569,6 @@ public final class NodeManager {
if ((props[i] == null) || !props[i].dirty) { if ((props[i] == null) || !props[i].dirty) {
// null out clean property so we don't consider it later // null out clean property so we don't consider it later
props[i] = null; props[i] = null;
continue; continue;
} }
@ -1673,9 +1669,11 @@ public final class NodeManager {
for (int i = 0; i < columns.length; i++) { for (int i = 0; i < columns.length; i++) {
int columnNumber = i + 1 + offset;
// set prototype? // set prototype?
if (columns[i].isPrototypeField()) { if (columns[i].isPrototypeField()) {
String protoId = rs.getString(i + 1 + offset); String protoId = rs.getString(columnNumber);
protoName = dbm.getPrototypeName(protoId); protoName = dbm.getPrototypeName(protoId);
if (protoName != null) { if (protoName != null) {
@ -1693,7 +1691,7 @@ public final class NodeManager {
// set id? // set id?
if (columns[i].isIdField()) { if (columns[i].isIdField()) {
id = rs.getString(i + 1 + offset); id = rs.getString(columnNumber);
// if id == null, the object doesn't actually exist - return null // if id == null, the object doesn't actually exist - return null
if (id == null) { if (id == null) {
return null; return null;
@ -1702,14 +1700,14 @@ public final class NodeManager {
// set name? // set name?
if (columns[i].isNameField()) { if (columns[i].isNameField()) {
name = rs.getString(i + 1 + offset); name = rs.getString(columnNumber);
} }
Property newprop = new Property(node); Property newprop = new Property(node);
switch (columns[i].getType()) { switch (columns[i].getType()) {
case Types.BIT: case Types.BIT:
newprop.setBooleanValue(rs.getBoolean(i + 1 + offset)); newprop.setBooleanValue(rs.getBoolean(columnNumber));
break; break;
@ -1717,21 +1715,21 @@ public final class NodeManager {
case Types.BIGINT: case Types.BIGINT:
case Types.SMALLINT: case Types.SMALLINT:
case Types.INTEGER: case Types.INTEGER:
newprop.setIntegerValue(rs.getLong(i + 1 + offset)); newprop.setIntegerValue(rs.getLong(columnNumber));
break; break;
case Types.REAL: case Types.REAL:
case Types.FLOAT: case Types.FLOAT:
case Types.DOUBLE: case Types.DOUBLE:
newprop.setFloatValue(rs.getDouble(i + 1 + offset)); newprop.setFloatValue(rs.getDouble(columnNumber));
break; break;
case Types.DECIMAL: case Types.DECIMAL:
case Types.NUMERIC: case Types.NUMERIC:
BigDecimal num = rs.getBigDecimal(i + 1 + offset); BigDecimal num = rs.getBigDecimal(columnNumber);
if (num == null) { if (num == null) {
break; break;
@ -1747,33 +1745,39 @@ public final class NodeManager {
case Types.VARBINARY: case Types.VARBINARY:
case Types.BINARY: case Types.BINARY:
newprop.setStringValue(rs.getString(i + 1 + offset)); newprop.setJavaObjectValue(rs.getBytes(columnNumber));
break; break;
case Types.BLOB:
case Types.LONGVARBINARY: case Types.LONGVARBINARY:
try {
newprop.setJavaObjectValue(rs.getBytes(columnNumber));
} catch (SQLException x) {
InputStream in = rs.getBinaryStream(columnNumber);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int read;
while ((read = in.read(buffer)) > -1) {
bout.write(buffer, 0, read);
}
newprop.setJavaObjectValue(bout.toByteArray());
}
break;
case Types.LONGVARCHAR: case Types.LONGVARCHAR:
try { try {
newprop.setStringValue(rs.getString(i + 1 + offset)); newprop.setStringValue(rs.getString(columnNumber));
} catch (SQLException x) { } catch (SQLException x) {
Reader in = rs.getCharacterStream(i + 1 + offset); Reader in = rs.getCharacterStream(columnNumber);
StringBuffer out = new StringBuffer();
char[] buffer = new char[2048]; char[] buffer = new char[2048];
int read = 0; int read;
int r; while ((read = in.read(buffer)) > -1) {
out.append(buffer, 0, read);
while ((r = in.read(buffer, read, buffer.length - read)) > -1) {
read += r;
if (read == buffer.length) {
// grow input buffer
char[] newBuffer = new char[buffer.length * 2];
System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
buffer = newBuffer;
}
} }
newprop.setStringValue(out.toString());
newprop.setStringValue(new String(buffer, 0, read));
} }
break; break;
@ -1781,14 +1785,14 @@ public final class NodeManager {
case Types.CHAR: case Types.CHAR:
case Types.VARCHAR: case Types.VARCHAR:
case Types.OTHER: case Types.OTHER:
newprop.setStringValue(rs.getString(i + 1 + offset)); newprop.setStringValue(rs.getString(columnNumber));
break; break;
case Types.DATE: case Types.DATE:
case Types.TIME: case Types.TIME:
case Types.TIMESTAMP: case Types.TIMESTAMP:
newprop.setDateValue(rs.getTimestamp(i + 1 + offset)); newprop.setDateValue(rs.getTimestamp(columnNumber));
break; break;
@ -1798,7 +1802,7 @@ public final class NodeManager {
break; break;
case Types.CLOB: case Types.CLOB:
Clob cl = rs.getClob(i+1+offset); Clob cl = rs.getClob(columnNumber);
if (cl==null) { if (cl==null) {
newprop.setStringValue(null); newprop.setStringValue(null);
break; break;
@ -1810,7 +1814,7 @@ public final class NodeManager {
break; break;
default: default:
newprop.setStringValue(rs.getString(i + 1 + offset)); newprop.setStringValue(rs.getString(columnNumber));
break; break;
} }
@ -2004,14 +2008,14 @@ public final class NodeManager {
} }
} }
private void setStatementValue(PreparedStatement stmt, int stmtNumber, String value, DbColumn col) private void setStatementValue(PreparedStatement stmt, int columnNumber, String value, DbColumn col)
throws SQLException { throws SQLException {
if (value == null) { if (value == null) {
stmt.setNull(stmtNumber, col.getType()); stmt.setNull(columnNumber, col.getType());
} else if (col.needsQuotes()) { } else if (col.needsQuotes()) {
stmt.setString(stmtNumber, value); stmt.setString(columnNumber, value);
} else { } else {
stmt.setLong(stmtNumber, Long.parseLong(value)); stmt.setLong(columnNumber, Long.parseLong(value));
} }
} }
@ -2039,23 +2043,33 @@ public final class NodeManager {
break; break;
case Types.LONGVARBINARY:
case Types.VARBINARY: case Types.VARBINARY:
case Types.BINARY: case Types.BINARY:
case Types.BLOB: case Types.BLOB:
stmt.setString(stmtNumber, p.getStringValue()); Object b = p.getJavaObjectValue();
if (b instanceof byte[]) {
byte[] buf = (byte[]) b;
try {
stmt.setBytes(stmtNumber, buf);
} catch (SQLException x) {
ByteArrayInputStream bout = new ByteArrayInputStream(buf);
stmt.setBinaryStream(stmtNumber, bout, buf.length);
}
} else {
throw new SQLException("expected byte[] for binary column '" +
p.getName() + "', found " + b.getClass());
}
break; break;
case Types.LONGVARBINARY:
case Types.LONGVARCHAR: case Types.LONGVARCHAR:
try { try {
stmt.setString(stmtNumber, p.getStringValue()); stmt.setString(stmtNumber, p.getStringValue());
} catch (SQLException x) { } catch (SQLException x) {
String str = p.getStringValue(); String str = p.getStringValue();
Reader r = new StringReader(str); Reader r = new StringReader(str);
stmt.setCharacterStream(stmtNumber, r, str.length());
stmt.setCharacterStream(stmtNumber, r,
str.length());
} }
break; break;

View file

@ -329,6 +329,7 @@ public final class Property implements IProperty, Serializable, Cloneable, Compa
public void setJavaObjectValue(Object obj) { public void setJavaObjectValue(Object obj) {
type = JAVAOBJECT; type = JAVAOBJECT;
value = obj; value = obj;
dirty = true;
} }