in HSQL/src/org/hsqldb1/util/SqlFile.java [2898:3302]
private void displayResultSet(Statement statement, ResultSet r,
int[] incCols,
String filter) throws SQLException,
SqlToolError {
java.sql.Timestamp ts;
int dotAt;
int updateCount = (statement == null) ? -1
: statement
.getUpdateCount();
boolean silent = silentFetch;
boolean binary = fetchBinary;
silentFetch = false;
fetchBinary = false;
if (excludeSysSchemas) {
stdprintln(rb.getString(SqltoolRB.VENDOR_NOSUP_SYSSCHEMAS));
}
switch (updateCount) {
case -1 :
if (r == null) {
stdprintln(rb.getString(SqltoolRB.NORESULT), true);
break;
}
ResultSetMetaData m = r.getMetaData();
int cols = m.getColumnCount();
int incCount = (incCols == null) ? cols
: incCols
.length;
String val;
List rows = new ArrayList();
String[] headerArray = null;
String[] fieldArray;
int[] maxWidth = new int[incCount];
int insi;
boolean skip;
// STEP 1: GATHER DATA
if (!htmlMode) {
for (int i = 0; i < maxWidth.length; i++) {
maxWidth[i] = 0;
}
}
boolean[] rightJust = new boolean[incCount];
int[] dataType = new int[incCount];
boolean[] autonulls = new boolean[incCount];
insi = -1;
headerArray = new String[incCount];
for (int i = 1; i <= cols; i++) {
if (incCols != null) {
skip = true;
for (int j = 0; j < incCols.length; j++) {
if (i == incCols[j]) {
skip = false;
}
}
if (skip) {
continue;
}
}
headerArray[++insi] = m.getColumnLabel(i);
dataType[insi] = m.getColumnType(i);
rightJust[insi] = false;
autonulls[insi] = true;
switch (dataType[insi]) {
case java.sql.Types.BIGINT :
case java.sql.Types.BIT :
case java.sql.Types.DECIMAL :
case java.sql.Types.DOUBLE :
case java.sql.Types.FLOAT :
case java.sql.Types.INTEGER :
case java.sql.Types.NUMERIC :
case java.sql.Types.REAL :
case java.sql.Types.SMALLINT :
case java.sql.Types.TINYINT :
rightJust[insi] = true;
break;
case java.sql.Types.VARBINARY :
case java.sql.Types.VARCHAR :
case java.sql.Types.ARRAY :
// Guessing at how to handle ARRAY.
case java.sql.Types.BLOB :
case java.sql.Types.CLOB :
case java.sql.Types.LONGVARBINARY :
case java.sql.Types.LONGVARCHAR :
autonulls[insi] = false;
break;
}
if (htmlMode) {
continue;
}
if (headerArray[insi].length() > maxWidth[insi]) {
maxWidth[insi] = headerArray[insi].length();
}
}
boolean filteredOut;
while (r.next()) {
fieldArray = new String[incCount];
insi = -1;
filteredOut = filter != null;
for (int i = 1; i <= cols; i++) {
// This is the only case where we can save a data
// read by recognizing we don't need this datum early.
if (incCols != null) {
skip = true;
for (int j = 0; j < incCols.length; j++) {
if (i == incCols[j]) {
skip = false;
}
}
if (skip) {
continue;
}
}
// This row may still be ditched, but it is now
// certain that we need to increment the fieldArray
// index.
++insi;
if (!SqlFile.canDisplayType(dataType[insi])) {
binary = true;
}
val = null;
if (!binary) {
/*
* The special formatting for all time-related
* fields is because the most popular current
* databases are extremely inconsistent about
* what resolution is returned for the same types.
* In my experience so far, Dates MAY have
* resolution down to second, but only TIMESTAMPs
* support sub-second res. (and always can).
* On top of that there is no consistency across
* getObject().toString(). Oracle doesn't even
* implement it for their custom TIMESTAMP type.
*/
switch (dataType[insi]) {
case java.sql.Types.TIMESTAMP:
case java.sql.Types.DATE:
case java.sql.Types.TIME:
ts = r.getTimestamp(i);
val = ((ts == null) ? null : ts.toString());
// Following block truncates non-zero
// sub-seconds from time types OTHER than
// TIMESTAMP.
if (dataType[insi]
!= java.sql.Types.TIMESTAMP
&& val != null) {
dotAt = val.lastIndexOf('.');
for (int z = dotAt + 1;
z < val.length(); z++) {
if (val.charAt(z) != '0') {
dotAt = 0;
break;
}
}
if (dotAt > 1) {
val = val.substring(0, dotAt);
}
}
break;
default:
val = r.getString(i);
// If we tried to get a String but it
// failed, try getting it with a String
// Stream
if (val == null) {
try {
val = streamToString(
r.getAsciiStream(i), charset);
} catch (Exception e) { }
}
}
}
if (binary || (val == null &&!r.wasNull())) {
if (pwDsv != null) {
throw new SqlToolError(
rb.getString(SqltoolRB.DSV_BINCOL));
}
// DB has a value but we either explicitly want
// it as binary, or we failed to get it as String.
try {
binBuffer =
SqlFile.streamToBytes(r.getBinaryStream(i));
} catch (IOException ioe) {
throw new SqlToolError(
"Failed to read value using stream",
ioe);
}
stdprintln(rb.getString(SqltoolRB.BINBUF_WRITE,
Integer.toString(binBuffer.length),
headerArray[insi],
SqlFile.sqlTypeToString(dataType[insi])
));
return;
}
if (excludeSysSchemas && val != null && i == 2) {
for (int z = 0; z < oracleSysSchemas.length;
z++) {
if (val.equals(oracleSysSchemas[z])) {
filteredOut = true;
break;
}
}
}
userVars.put("?", ((val == null) ? nullRepToken : val));
if (fetchingVar != null) {
userVars.put(fetchingVar, userVars.get("?"));
updateUserSettings();
fetchingVar = null;
}
if (silent) {
return;
}
// We do not omit rows here. We collect information
// so we can make the decision after all rows are
// read in.
if (filter != null
&& (val == null
|| val.indexOf(filter) > -1)) {
filteredOut = false;
}
///////////////////////////////
// A little tricky here. fieldArray[] MUST get set.
if (val == null && pwDsv == null) {
if (dataType[insi] == java.sql.Types.VARCHAR) {
fieldArray[insi] = (htmlMode ? "<I>null</I>"
: nullRepToken);
} else {
fieldArray[insi] = "";
}
} else {
fieldArray[insi] = val;
}
///////////////////////////////
if (htmlMode || pwDsv != null) {
continue;
}
if (fieldArray[insi].length() > maxWidth[insi]) {
maxWidth[insi] = fieldArray[insi].length();
}
}
if (!filteredOut) {
rows.add(fieldArray);
}
}
// STEP 2: DISPLAY DATA (= 2a OR 2b)
// STEP 2a (Non-DSV)
if (pwDsv == null) {
condlPrintln("<TABLE border='1'>", true);
if (incCount > 1) {
condlPrint(SqlFile.htmlRow(COL_HEAD) + LS + PRE_TD, true);
for (int i = 0; i < headerArray.length; i++) {
condlPrint("<TD>" + headerArray[i] + "</TD>",
true);
condlPrint(((i > 0) ? SqlFile.spaces(2)
: "") + SqlFile.pad(
headerArray[i],
maxWidth[i],
rightJust[i],
(i < headerArray.length
- 1 || rightJust[i])), false);
}
condlPrintln(LS + PRE_TR + "</TR>", true);
condlPrintln("", false);
if (!htmlMode) {
for (int i = 0; i < headerArray.length; i++) {
condlPrint(((i > 0) ? SqlFile.spaces(2)
: "") + SqlFile.divider(
maxWidth[i]), false);
}
condlPrintln("", false);
}
}
for (int i = 0; i < rows.size(); i++) {
condlPrint(SqlFile.htmlRow(((i % 2) == 0) ? COL_EVEN
: COL_ODD) + LS
+ PRE_TD, true);
fieldArray = (String[]) rows.get(i);
for (int j = 0; j < fieldArray.length; j++) {
condlPrint("<TD>" + fieldArray[j] + "</TD>",
true);
condlPrint(((j > 0) ? SqlFile.spaces(2)
: "") + SqlFile.pad(
fieldArray[j],
maxWidth[j],
rightJust[j],
(j < fieldArray.length
- 1 || rightJust[j])), false);
}
condlPrintln(LS + PRE_TR + "</TR>", true);
condlPrintln("", false);
}
condlPrintln("</TABLE>", true);
if (rows.size() != 1) {
stdprintln(LS + rb.getString(SqltoolRB.ROWS_FETCHED,
rows.size()), true);
}
condlPrintln("<HR>", true);
break;
}
// STEP 2b (DSV)
if (incCount > 0) {
for (int i = 0; i < headerArray.length; i++) {
dsvSafe(headerArray[i]);
pwDsv.print(headerArray[i]);
if (i < headerArray.length - 1) {
pwDsv.print(dsvColDelim);
}
}
pwDsv.print(dsvRowDelim);
}
for (int i = 0; i < rows.size(); i++) {
fieldArray = (String[]) rows.get(i);
for (int j = 0; j < fieldArray.length; j++) {
dsvSafe(fieldArray[j]);
pwDsv.print((fieldArray[j] == null)
? (autonulls[j] ? ""
: nullRepToken)
: fieldArray[j]);
if (j < fieldArray.length - 1) {
pwDsv.print(dsvColDelim);
}
}
pwDsv.print(dsvRowDelim);
}
stdprintln(rb.getString(SqltoolRB.ROWS_FETCHED_DSV,
rows.size()));
break;
default :
userVars.put("?", Integer.toString(updateCount));
if (fetchingVar != null) {
userVars.put(fetchingVar, userVars.get("?"));
updateUserSettings();
fetchingVar = null;
}
if (updateCount != 0) {
stdprintln((updateCount == 1)
? rb.getString(SqltoolRB.ROW_UPDATE_SINGULAR)
: rb.getString(SqltoolRB.ROW_UPDATE_MULTIPLE,
updateCount));
}
break;
}
}