diff --git a/Model/src/main/java/org/gusdb/wdk/model/answer/AnswerValue.java b/Model/src/main/java/org/gusdb/wdk/model/answer/AnswerValue.java index 6b999c370..7f9870c67 100644 --- a/Model/src/main/java/org/gusdb/wdk/model/answer/AnswerValue.java +++ b/Model/src/main/java/org/gusdb/wdk/model/answer/AnswerValue.java @@ -366,23 +366,29 @@ public String getAnswerTableSql(Query tableQuery) getPagedTableSql(tableQuery); } - public ResultList getTableFieldResultList(TableField tableField) throws WdkModelException { - + public String getTableFieldResultSql(TableField tableField) throws WdkModelException { // has to get a clean copy of the attribute query, without pk params appended Query tableQuery = tableField.getUnwrappedQuery(); // get and run the paged table query sql - LOG.debug("AnswerValue: getTableFieldResultList(): going to getPagedTableSql()"); + LOG.debug("AnswerValue: getTableFieldResultSql(): going to getPagedTableSql()"); + + return getAnswerTableSql(tableQuery); + } + + public ResultList getTableFieldResultList(TableField tableField) throws WdkModelException { + return getTableFieldResultList(tableField, getTableFieldResultSql(tableField)); + } + + public ResultList getTableFieldResultList(TableField tableField, String customSql) throws WdkModelException { - String sql = getAnswerTableSql(tableQuery); - LOG.debug("AnswerValue: getTableFieldResultList(): back from getPagedTableSql()"); DatabaseInstance platform = _wdkModel.getAppDb(); DataSource dataSource = platform.getDataSource(); ResultSet resultSet = null; try { - LOG.debug("AnswerValue: getTableFieldResultList(): returning SQL for TableField '" + tableField.getName() + "': \n" + sql); - resultSet = SqlUtils.executeQuery(dataSource, sql, tableQuery.getFullName() + "_table"); + LOG.debug("AnswerValue: getTableFieldResultList(): returning SQL for TableField '" + tableField.getName() + "': \n" + customSql); + resultSet = SqlUtils.executeQuery(dataSource, customSql, tableField.getUnwrappedQuery().getFullName() + "_table"); } catch (SQLException e) { throw new WdkModelException(e); diff --git a/Model/src/main/java/org/gusdb/wdk/model/answer/stream/SingleTableRecordStream.java b/Model/src/main/java/org/gusdb/wdk/model/answer/stream/SingleTableRecordStream.java index 175740c13..91d8a8678 100644 --- a/Model/src/main/java/org/gusdb/wdk/model/answer/stream/SingleTableRecordStream.java +++ b/Model/src/main/java/org/gusdb/wdk/model/answer/stream/SingleTableRecordStream.java @@ -6,6 +6,8 @@ import java.util.Map; import java.util.NoSuchElementException; +import org.apache.log4j.Logger; +import org.gusdb.fgputil.Timer; import org.gusdb.fgputil.Wrapper; import org.gusdb.fgputil.iterator.ReadOnlyIterator; import org.gusdb.wdk.model.WdkModelException; @@ -23,6 +25,8 @@ public class SingleTableRecordStream implements RecordStream { + private static final Logger LOG = Logger.getLogger(SingleTableRecordStream.class); + private AnswerValue _answerValue; private TableField _tableField; private PrimaryKeyDefinition _pkDef; @@ -34,6 +38,10 @@ public SingleTableRecordStream(AnswerValue answerValue, TableField tableField) t init(answerValue, tableField, answerValue.getTableFieldResultList(tableField)); } + public SingleTableRecordStream(AnswerValue answerValue, TableField tableField, String customTableSql) throws WdkModelException { + init(answerValue, tableField, answerValue.getTableFieldResultList(tableField, customTableSql)); + } + public SingleTableRecordStream(AnswerValue answerValue, TableField tableField, ResultList resultList) { init(answerValue, tableField, resultList); } @@ -84,6 +92,8 @@ public RecordInstance next() { _lastPkValues.set(null); // will reset if there is another record after this one // loop through the ResultList's rows and add to table until PK values differ + int rowCount = 0; + Timer t = new Timer(); while (_resultList.next()) { Map rowPkValues = new PrimaryKeyValue(_pkDef, _resultList).getRawValues(); if (rawValuesDiffer(currentRecordPkValues, rowPkValues)) { @@ -92,6 +102,10 @@ public RecordInstance next() { return record; } // otherwise add row to table value + rowCount++; + LOG.trace("Row " + rowCount + ": fetched in " + t.getElapsedStringAndRestart()); + if (rowCount > TableValue.MAX_TABLE_VALUE_ROWS) + throw new WdkRuntimeException("Table query returned too many (>" + TableValue.MAX_TABLE_VALUE_ROWS + ") rows."); tableValue.initializeRow(_resultList); } diff --git a/Model/src/main/java/org/gusdb/wdk/model/record/DynamicTableValue.java b/Model/src/main/java/org/gusdb/wdk/model/record/DynamicTableValue.java index 751153d31..890f29e0e 100644 --- a/Model/src/main/java/org/gusdb/wdk/model/record/DynamicTableValue.java +++ b/Model/src/main/java/org/gusdb/wdk/model/record/DynamicTableValue.java @@ -3,6 +3,7 @@ import java.util.Iterator; import org.apache.log4j.Logger; +import org.gusdb.fgputil.Timer; import org.gusdb.wdk.model.WdkModelException; import org.gusdb.wdk.model.WdkRuntimeException; import org.gusdb.wdk.model.answer.AnswerValue; @@ -36,7 +37,12 @@ public DynamicTableValue(PrimaryKeyValue primaryKey, TableField tableField, User private void loadRowsFromQuery() { try (ResultList resultList = _queryInstance.getResults()) { + int rowCount = 0; + Timer t = new Timer(); while (resultList.next()) { + LOG.trace("Row " + (++rowCount) + ": fetched in " + t.getElapsedStringAndRestart()); + if (rowCount > MAX_TABLE_VALUE_ROWS) + throw new WdkRuntimeException("Table query returned too many (>" + MAX_TABLE_VALUE_ROWS + ") rows."); initializeRow(resultList); } } diff --git a/Model/src/main/java/org/gusdb/wdk/model/record/TableValue.java b/Model/src/main/java/org/gusdb/wdk/model/record/TableValue.java index bb463db0f..c87b98280 100644 --- a/Model/src/main/java/org/gusdb/wdk/model/record/TableValue.java +++ b/Model/src/main/java/org/gusdb/wdk/model/record/TableValue.java @@ -31,6 +31,8 @@ */ public class TableValue implements Iterable { + public static final int MAX_TABLE_VALUE_ROWS = 30000; + protected final TableField _tableField; protected List _rows; diff --git a/Model/src/main/java/org/gusdb/wdk/model/report/reporter/TableTabularReporter.java b/Model/src/main/java/org/gusdb/wdk/model/report/reporter/TableTabularReporter.java index dfcb42787..e751df812 100644 --- a/Model/src/main/java/org/gusdb/wdk/model/report/reporter/TableTabularReporter.java +++ b/Model/src/main/java/org/gusdb/wdk/model/report/reporter/TableTabularReporter.java @@ -11,10 +11,8 @@ import org.gusdb.wdk.model.WdkModelException; import org.gusdb.wdk.model.WdkUserException; -import org.gusdb.wdk.model.answer.single.SingleRecordAnswerValue; import org.gusdb.wdk.model.answer.stream.FileBasedRecordStream; import org.gusdb.wdk.model.answer.stream.RecordStream; -import org.gusdb.wdk.model.answer.stream.SingleRecordStream; import org.gusdb.wdk.model.answer.stream.SingleTableRecordStream; import org.gusdb.wdk.model.record.RecordClass; import org.gusdb.wdk.model.record.RecordInstance; @@ -26,7 +24,7 @@ public class TableTabularReporter extends AbstractTabularReporter { - private TableField _tableField; + protected TableField _tableField; private Collection _tableAttributes; @Override @@ -58,6 +56,7 @@ private TableTabularReporter setTable() throws ReporterConfigException { */ @Override public RecordStream getRecords() throws WdkModelException { + /* Test to see if this case is necessary- may be ok to fall down to SingleTableRecordStream if (_baseAnswer instanceof SingleRecordAnswerValue) { try { return new SingleRecordStream((SingleRecordAnswerValue)_baseAnswer); @@ -65,7 +64,7 @@ public RecordStream getRecords() throws WdkModelException { catch (WdkUserException e) { throw new WdkModelException(e.getMessage(), e); } - } + } */ RecordClass recordClass = _baseAnswer.getQuestion().getRecordClass(); if (idAttributeContainsNonPkFields(recordClass)) { // need to use FileBasedRecordStream to support both this table and any needed attributes @@ -75,10 +74,14 @@ public RecordStream getRecords() throws WdkModelException { } else { // the records returned by this stream will have only PK and this single table field populated - return new SingleTableRecordStream(_baseAnswer, _tableField); + return getSingleTableRecordStream(); } } + protected RecordStream getSingleTableRecordStream() throws WdkModelException { + return new SingleTableRecordStream(_baseAnswer, _tableField); + } + private static boolean idAttributeContainsNonPkFields(RecordClass recordClass) throws WdkModelException { Collection deps = recordClass.getIdAttributeField().getDependencies(); List pkColumns = Arrays.asList(recordClass.getPrimaryKeyDefinition().getColumnRefs());