selectively including different table types when iterating the tables
in a Database.
</action>
+ <action dev="jahlborn" type="add" system="SourceForge2Features" issue="29">
+ Lowered the log level for certain warnings related to system tables
+ which do not generally affect jackcess functionality.
+ </action>
+ <action dev="jahlborn" type="add" system="SourceForge2Features" issue="29">
+ Added contextual information to many errors and warnings.
+ </action>
</release>
<release version="2.0.8" date="2014-12-26">
<action dev="jahlborn" type="fix" system="SourceForge2" issue="113">
private final int _updateCount;
- public BatchUpdateException(int updateCount, Throwable cause) {
- super(cause);
+ public BatchUpdateException(int updateCount, String msg, Throwable cause) {
+ super(msg + ": " + cause, cause);
_updateCount = updateCount;
}
*/
public void validate(JetFormat format) {
if(getType() == null) {
- throw new IllegalArgumentException("must have type");
+ throw new IllegalArgumentException(withErrorContext("must have type"));
}
DatabaseImpl.validateIdentifierName(
getName(), format.MAX_COLUMN_NAME_LENGTH, "column");
if(getType().isUnsupported()) {
- throw new IllegalArgumentException(
- "Cannot create column with unsupported type " + getType());
+ throw new IllegalArgumentException(withErrorContext(
+ "Cannot create column with unsupported type " + getType()));
}
if(!format.isSupportedDataType(getType())) {
- throw new IllegalArgumentException(
- "Database format " + format + " does not support type " + getType());
+ throw new IllegalArgumentException(withErrorContext(
+ "Database format " + format + " does not support type " + getType()));
}
if(!getType().isVariableLength()) {
if(getLength() != getType().getFixedSize()) {
if(getLength() < getType().getFixedSize()) {
- throw new IllegalArgumentException("invalid fixed length size");
+ throw new IllegalArgumentException(withErrorContext(
+ "invalid fixed length size"));
}
- LOG.warn("Column length " + getLength() +
- " longer than expected fixed size " +
- getType().getFixedSize());
+ LOG.warn(withErrorContext(
+ "Column length " + getLength() +
+ " longer than expected fixed size " + getType().getFixedSize()));
}
} else if(!getType().isLongValue()) {
if(!getType().isValidSize(getLength())) {
- throw new IllegalArgumentException("var length out of range");
+ throw new IllegalArgumentException(withErrorContext(
+ "var length out of range"));
}
}
if(getType().getHasScalePrecision()) {
if(!getType().isValidScale(getScale())) {
- throw new IllegalArgumentException(
+ throw new IllegalArgumentException(withErrorContext(
"Scale must be from " + getType().getMinScale() + " to " +
- getType().getMaxScale() + " inclusive");
+ getType().getMaxScale() + " inclusive"));
}
if(!getType().isValidPrecision(getPrecision())) {
- throw new IllegalArgumentException(
+ throw new IllegalArgumentException(withErrorContext(
"Precision must be from " + getType().getMinPrecision() + " to " +
- getType().getMaxPrecision() + " inclusive");
+ getType().getMaxPrecision() + " inclusive"));
}
}
if(isAutoNumber()) {
if(!getType().mayBeAutoNumber()) {
- throw new IllegalArgumentException(
- "Auto number column must be long integer or guid");
+ throw new IllegalArgumentException(withErrorContext(
+ "Auto number column must be long integer or guid"));
}
}
if(isCompressedUnicode()) {
if(!getType().isTextual()) {
- throw new IllegalArgumentException(
- "Only textual columns allow unicode compression (text/memo)");
+ throw new IllegalArgumentException(withErrorContext(
+ "Only textual columns allow unicode compression (text/memo)"));
}
}
if(isHyperlink()) {
if(getType() != DataType.MEMO) {
- throw new IllegalArgumentException(
- "Only memo columns can be hyperlinks");
+ throw new IllegalArgumentException(withErrorContext(
+ "Only memo columns can be hyperlinks"));
}
}
if(isCalculated()) {
if(!format.isSupportedCalculatedDataType(getType())) {
- throw new IllegalArgumentException(
+ throw new IllegalArgumentException(withErrorContext(
"Database format " + format + " does not support calculated type " +
- getType());
+ getType()));
}
// must have an expression
if(getProperty(PropertyMap.EXPRESSION_PROP) == null) {
- throw new IllegalArgumentException(
- "No expression provided for calculated type " + getType());
+ throw new IllegalArgumentException(withErrorContext(
+ "No expression provided for calculated type " + getType()));
}
// must have result type (just fill in if missing)
// for backwards compat w/ old code
return this;
}
-
+
+ private String withErrorContext(String msg) {
+ return msg + "(Column=" + getName() + ")";
+ }
}
getName(), format.MAX_INDEX_NAME_LENGTH, "index");
if(getColumns().isEmpty()) {
- throw new IllegalArgumentException("index " + getName() +
- " has no columns");
+ throw new IllegalArgumentException(withErrorContext(
+ "index has no columns"));
}
if(getColumns().size() > IndexData.MAX_COLUMNS) {
- throw new IllegalArgumentException("index " + getName() +
- " has too many columns, max " +
- IndexData.MAX_COLUMNS);
+ throw new IllegalArgumentException(withErrorContext(
+ "index has too many columns, max " + IndexData.MAX_COLUMNS));
}
Set<String> idxColNames = new HashSet<String>();
for(Column col : getColumns()) {
String idxColName = col.getName().toUpperCase();
if(!idxColNames.add(idxColName)) {
- throw new IllegalArgumentException("duplicate column name " +
- col.getName() + " in index " +
- getName());
+ throw new IllegalArgumentException(withErrorContext(
+ "duplicate column name " + col.getName() + " in index"));
}
if(!tableColNames.contains(idxColName)) {
- throw new IllegalArgumentException("column named " + col.getName() +
- " not found in table");
+ throw new IllegalArgumentException(withErrorContext(
+ "column named " + col.getName() + " not found in table"));
}
}
}
+ private String withErrorContext(String msg) {
+ return msg + "(Index=" + getName() + ")";
+ }
+
/**
* Information about a column in this index (name and ordering).
*/
* Creates the appropriate ColumnImpl class for a calculated column and
* reads a column definition in from a buffer
*
- * @param table owning table
- * @param buffer Buffer containing column definition
- * @param offset Offset in the buffer at which the column definition starts
+ * @param args column construction info
* @usage _advanced_method_
*/
static ColumnImpl create(ColumnImpl.InitArgs args) throws IOException
// check precision
if(decVal.precision() > getType().getMaxPrecision()) {
- throw new IOException(
+ throw new IOException(withErrorContext(
"Numeric value is too big for specified precision "
- + getType().getMaxPrecision() + ": " + decVal);
+ + getType().getMaxPrecision() + ": " + decVal));
}
// convert to unscaled BigInteger, big-endian bytes
try {
args.type = DataType.fromByte(colType);
} catch(IOException e) {
- LOG.warn("Unsupported column type " + colType);
+ LOG.warn(withErrorContext("Unsupported column type " + colType,
+ table.getDatabase(), table.getName(), name));
boolean variableLength = ((args.flags & FIXED_LEN_FLAG_MASK) == 0);
args.type = (variableLength ? DataType.UNSUPPORTED_VARLEN :
DataType.UNSUPPORTED_FIXEDLEN);
// cannot set autonumber validator (autonumber values are controlled
// internally)
if(newValidator != null) {
- throw new IllegalArgumentException(
- "Cannot set ColumnValidator for autonumber columns");
+ throw new IllegalArgumentException(withErrorContext(
+ "Cannot set ColumnValidator for autonumber columns"));
}
// just leave default validator instance alone
return;
case COMPLEX_TYPE:
return new ComplexTypeAutoNumberGenerator();
default:
- LOG.warn("Unknown auto number column type " + _type);
+ LOG.warn(withErrorContext("Unknown auto number column type " + _type));
return new UnsupportedAutoNumberGenerator(_type);
}
}
switch(getType()) {
case BOOLEAN:
- throw new IOException("Tried to read a boolean from data instead of null mask.");
+ throw new IOException(withErrorContext("Tried to read a boolean from data instead of null mask."));
case BYTE:
return Byte.valueOf(buffer.get());
case INT:
case COMPLEX_TYPE:
return new ComplexValueForeignKeyImpl(this, buffer.getInt());
default:
- throw new IOException("Unrecognized data type: " + _type);
+ throw new IOException(withErrorContext("Unrecognized data type: " + _type));
}
}
* @return BigDecimal representing the monetary value
* @throws IOException if the value cannot be parsed
*/
- private static BigDecimal readCurrencyValue(ByteBuffer buffer)
+ private BigDecimal readCurrencyValue(ByteBuffer buffer)
throws IOException
{
if(buffer.remaining() != 8) {
- throw new IOException("Invalid money value.");
+ throw new IOException(withErrorContext("Invalid money value"));
}
return new BigDecimal(BigInteger.valueOf(buffer.getLong(0)), 4);
// check precision
if(decVal.precision() > getPrecision()) {
- throw new IOException(
+ throw new IOException(withErrorContext(
"Numeric value is too big for specified precision "
- + getPrecision() + ": " + decVal);
+ + getPrecision() + ": " + decVal));
}
// convert to unscaled BigInteger, big-endian bytes
}
}
- static byte[] toUnscaledByteArray(BigDecimal decVal, int maxByteLen)
+ byte[] toUnscaledByteArray(BigDecimal decVal, int maxByteLen)
throws IOException
{
// convert to unscaled BigInteger, big-endian bytes
// with unsigned values, so we can drop the extra leading 0
intValBytes = ByteUtil.copyOf(intValBytes, 1, maxByteLen);
} else {
- throw new IOException("Too many bytes for valid BigInteger?");
+ throw new IOException(withErrorContext(
+ "Too many bytes for valid BigInteger?"));
}
} else if(intValBytes.length < maxByteLen) {
intValBytes = ByteUtil.copyOf(intValBytes, 0, maxByteLen,
/**
* Writes a GUID value.
*/
- private static void writeGUIDValue(ByteBuffer buffer, Object value)
+ private void writeGUIDValue(ByteBuffer buffer, Object value)
throws IOException
{
Matcher m = GUID_PATTERN.matcher(toCharSequence(value));
if(!m.matches()) {
- throw new IOException("Invalid GUID: " + value);
+ throw new IOException(withErrorContext("Invalid GUID: " + value));
}
ByteBuffer origBuffer = null;
// should already be "encoded"
break;
default:
- throw new RuntimeException("unexpected inline var length type: " +
- getType());
+ throw new RuntimeException(withErrorContext(
+ "unexpected inline var length type: " + getType()));
}
ByteBuffer buffer = ByteBuffer.wrap(toByteArray(obj)).order(order);
case UNSUPPORTED_FIXEDLEN:
byte[] bytes = toByteArray(obj);
if(bytes.length != getLength()) {
- throw new IOException("Invalid fixed size binary data, size "
- + getLength() + ", got " + bytes.length);
+ throw new IOException(withErrorContext(
+ "Invalid fixed size binary data, size "
+ + getLength() + ", got " + bytes.length));
}
buffer.put(bytes);
break;
default:
- throw new IOException("Unsupported data type: " + getType());
+ throw new IOException(withErrorContext(
+ "Unsupported data type: " + getType()));
}
return buffer;
}
{
CharSequence text = toCharSequence(obj);
if((text.length() > maxChars) || (text.length() < minChars)) {
- throw new IOException("Text is wrong length for " + getType() +
+ throw new IOException(withErrorContext(
+ "Text is wrong length for " + getType() +
" column, max " + maxChars
- + ", min " + minChars + ", got " + text.length());
+ + ", min " + minChars + ", got " + text.length()));
}
// may only compress if column type allows it
}
}
+ String withErrorContext(String msg) {
+ return withErrorContext(msg, getDatabase(), getTable().getName(), getName());
+ }
+
+ private static String withErrorContext(
+ String msg, DatabaseImpl db, String tableName, String colName) {
+ return msg + " (Db=" + db.getName() + ";Table=" + tableName + ";Column=" +
+ colName + ")";
+ }
+
/**
* Date subclass which stashes the original date bits, in case we attempt to
* re-write the value (will not lose precision).
IndexCursor cursor = CursorBuilder.createCursor(
complexColumns.getPrimaryKeyIndex());
if(!cursor.findFirstRowByEntry(complexTypeId)) {
- throw new IOException(
+ throw new IOException(column.withErrorContext(
"Could not find complex column info for complex column with id " +
- complexTypeId);
+ complexTypeId));
}
Row cColRow = cursor.getCurrentRow();
int tableId = cColRow.getInt(COL_TABLE_ID);
if(tableId != column.getTable().getTableDefPageNumber()) {
- throw new IOException(
+ throw new IOException(column.withErrorContext(
"Found complex column for table " + tableId + " but expected table " +
- column.getTable().getTableDefPageNumber());
+ column.getTable().getTableDefPageNumber()));
}
int flatTableId = cColRow.getInt(COL_FLAT_TABLE_ID);
int typeObjId = cColRow.getInt(COL_COMPLEX_TYPE_OBJECT_ID);
TableImpl flatTable = db.getTable(flatTableId);
if((typeObjTable == null) || (flatTable == null)) {
- throw new IOException(
+ throw new IOException(column.withErrorContext(
"Could not find supporting tables (" + typeObjId + ", " + flatTableId
- + ") for complex column with id " + complexTypeId);
+ + ") for complex column with id " + complexTypeId));
}
// we inspect the structore of the "type table" to determine what kind of
flatTable);
}
- LOG.warn("Unsupported complex column type " + typeObjTable.getName());
+ LOG.warn(column.withErrorContext(
+ "Unsupported complex column type " + typeObjTable.getName()));
return new UnsupportedColumnInfoImpl(column, complexTypeId, typeObjTable,
- flatTable);
+ flatTable);
}
/** the File of the database */
private final File _file;
+ /** the simple name of the database */
+ private final String _name;
/** Buffer to hold database pages */
private ByteBuffer _buffer;
/** ID of the Tables system object */
if(jetFormat.READ_ONLY) {
throw new IOException("jet format '" + jetFormat +
- "' does not support writing");
+ "' does not support writing for " + mdbFile);
}
}
DatabaseImpl db = new DatabaseImpl(mdbFile, channel, closeChannel, autoSync,
- null, charset, timeZone, provider);
+ null, charset, timeZone, provider);
success = true;
return db;
FileFormatDetails details = getFileFormatDetails(fileFormat);
if (details.getFormat().READ_ONLY) {
throw new IOException("file format " + fileFormat +
- " does not support writing");
+ " does not support writing for " + mdbFile);
}
boolean closeChannel = false;
throws IOException
{
_file = file;
+ _name = getName(file);
_format = JetFormat.getFormat(channel);
_charset = ((charset == null) ? getDefaultCharset(_format) : charset);
_columnOrder = getDefaultColumnOrder();
return _file;
}
+ public String getName() {
+ return _name;
+ }
+
/**
* @usage _advanced_method_
*/
*/
public TableImpl getAccessControlEntries() throws IOException {
if(_accessControlEntries == null) {
- _accessControlEntries = getSystemTable(TABLE_SYSTEM_ACES);
- if(_accessControlEntries == null) {
- throw new IOException("Could not find system table " +
- TABLE_SYSTEM_ACES);
- }
-
+ _accessControlEntries = getRequiredSystemTable(TABLE_SYSTEM_ACES);
}
return _accessControlEntries;
}
*/
public TableImpl getSystemComplexColumns() throws IOException {
if(_complexCols == null) {
- _complexCols = getSystemTable(TABLE_SYSTEM_COMPLEX_COLS);
- if(_complexCols == null) {
- throw new IOException("Could not find system table " +
- TABLE_SYSTEM_COMPLEX_COLS);
- }
+ _complexCols = getRequiredSystemTable(TABLE_SYSTEM_COMPLEX_COLS);
}
return _complexCols;
}
_fileFormat = possibleFileFormats.get(accessVersion);
if(_fileFormat == null) {
- throw new IllegalStateException("Could not determine FileFormat");
+ throw new IllegalStateException(withErrorContext(
+ "Could not determine FileFormat"));
}
}
}
.setColumnMatcher(CaseInsensitiveColumnMatcher.INSTANCE)
.toIndexCursor());
} catch(IllegalArgumentException e) {
- LOG.info("Could not find expected index on table " +
- _systemCatalog.getName());
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(withErrorContext(
+ "Could not find expected index on table " +
+ _systemCatalog.getName()));
+ }
// use table scan instead
_tableFinder = new FallbackTableFinder(
_systemCatalog.newCursor()
SYSTEM_OBJECT_NAME_TABLES);
if(_tableParentId == null) {
- throw new IOException("Did not find required parent table id");
+ throw new IOException(withErrorContext(
+ "Did not find required parent table id"));
}
if (LOG.isDebugEnabled()) {
- LOG.debug("Finished reading system catalog. Tables: " + getTableNames());
+ LOG.debug(withErrorContext(
+ "Finished reading system catalog. Tables: " + getTableNames()));
}
}
throws IOException
{
if(lookupTable(name) != null) {
- throw new IllegalArgumentException(
- "Cannot create table with name of existing table");
+ throw new IllegalArgumentException(withErrorContext(
+ "Cannot create table with name of existing table '" + name + "'"));
}
new TableCreator(this, name, columns, indexes).createTable();
throws IOException
{
if(lookupTable(name) != null) {
- throw new IllegalArgumentException(
- "Cannot create linked table with name of existing table");
+ throw new IllegalArgumentException(withErrorContext(
+ "Cannot create linked table with name of existing table '" + name +
+ "'"));
}
validateIdentifierName(name, getFormat().MAX_TABLE_NAME_LENGTH, "table");
{
int nameCmp = table1.getName().compareTo(table2.getName());
if(nameCmp == 0) {
- throw new IllegalArgumentException("Must provide two different tables");
+ throw new IllegalArgumentException(withErrorContext(
+ "Must provide two different tables"));
}
if(nameCmp > 0) {
// we "order" the two tables given so that we will return a collection
throws IOException
{
if(table == null) {
- throw new IllegalArgumentException("Must provide a table");
+ throw new IllegalArgumentException(withErrorContext("Must provide a table"));
}
// since we are getting relationships specific to certain table include
// all tables
{
// the relationships table does not get loaded until first accessed
if(_relationships == null) {
- _relationships = getSystemTable(TABLE_SYSTEM_RELATIONSHIPS);
- if(_relationships == null) {
- throw new IOException("Could not find system relationships table");
- }
+ _relationships = getRequiredSystemTable(TABLE_SYSTEM_RELATIONSHIPS);
}
List<Relationship> relationships = new ArrayList<Relationship>();
{
// the queries table does not get loaded until first accessed
if(_queries == null) {
- _queries = getSystemTable(TABLE_SYSTEM_QUERIES);
- if(_queries == null) {
- throw new IOException("Could not find system queries table");
- }
+ _queries = getRequiredSystemTable(TABLE_SYSTEM_QUERIES);
}
// find all the queries from the system catalog
QueryImpl.Row queryRow = new QueryImpl.Row(row);
List<QueryImpl.Row> queryRows = queryRowMap.get(queryRow.objectId);
if(queryRows == null) {
- LOG.warn("Found rows for query with id " + queryRow.objectId +
- " missing from system catalog");
+ LOG.warn(withErrorContext(
+ "Found rows for query with id " + queryRow.objectId +
+ " missing from system catalog"));
continue;
}
queryRows.add(queryRow);
return getTable(tableName, true);
}
+ private TableImpl getRequiredSystemTable(String tableName) throws IOException
+ {
+ TableImpl table = getSystemTable(tableName);
+ if(table == null) {
+ throw new IOException(withErrorContext(
+ "Could not find system table " + tableName));
+ }
+ return table;
+ }
+
public PropertyMap getDatabaseProperties() throws IOException {
if(_dbPropMaps == null) {
_dbPropMaps = getPropertiesForDbObject(OBJECT_NAME_DB_PROPS);
_dbParentId = _tableFinder.findObjectId(DB_PARENT_ID,
SYSTEM_OBJECT_NAME_DATABASES);
if(_dbParentId == null) {
- throw new IOException("Did not find required parent db id");
+ throw new IOException(withErrorContext(
+ "Did not find required parent db id"));
}
}
_pageChannel.readPage(buffer, pageNumber);
byte pageType = buffer.get(0);
if (pageType != PageTypes.TABLE_DEF) {
- throw new IOException(
+ throw new IOException(withErrorContext(
"Looking for " + name + " at page " + pageNumber +
- ", but page type is " + pageType);
+ ", but page type is " + pageType));
}
return _tableCache.put(
new TableImpl(this, buffer, pageNumber, name, flags));
* Creates a Cursor restricted to the given column value if possible (using
* an existing index), otherwise a simple table cursor.
*/
- private static Cursor createCursorWithOptionalIndex(
+ private Cursor createCursorWithOptionalIndex(
TableImpl table, String colName, Object colValue)
throws IOException
{
.setSpecificEntry(colValue)
.toCursor();
} catch(IllegalArgumentException e) {
- LOG.info("Could not find expected index on table " + table.getName());
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(withErrorContext(
+ "Could not find expected index on table " + table.getName()));
+ }
}
// use table scan instead
return CursorImpl.createCursor(table);
// additional identifier validation
if(INVALID_IDENTIFIER_CHARS.matcher(name).find()) {
throw new IllegalArgumentException(
- identifierType + " name contains invalid characters");
+ identifierType + " name '" + name + "' contains invalid characters");
}
// cannot start with spaces
if(name.charAt(0) == ' ') {
throw new IllegalArgumentException(
- identifierType + " name cannot start with a space character");
+ identifierType + " name '" + name +
+ "' cannot start with a space character");
}
}
FILE_FORMAT_DETAILS.put(fileFormat, new FileFormatDetails(emptyFile, format));
}
+ private static String getName(File file) {
+ if(file == null) {
+ return "<UNKNOWN.DB>";
+ }
+ return file.getName();
+ }
+
+ private String withErrorContext(String msg) {
+ return withErrorContext(msg, getName());
+ }
+
+ private static String withErrorContext(String msg, String dbName) {
+ return msg + " (Db=" + dbName + ")";
+ }
+
/**
* Utility class for storing table page number and actual name.
*/
int maxSynthId = findMaxSyntheticId();
if(maxSynthId >= -1) {
// bummer, no more ids available
- throw new IllegalStateException("Too many database objects!");
+ throw new IllegalStateException(withErrorContext(
+ "Too many database objects!"));
}
return maxSynthId + 1;
}
};
+ /** name, generated on demand */
+ private String _name;
/** owning table */
private final TableImpl _table;
/** 0-based index data number */
return new IndexData(table, number, uniqueEntryCount, uniqueEntryCountOffset);
}
+ public String getName() {
+ if(_name == null) {
+ if(_indexes.size() == 1) {
+ _name = _indexes.get(0).getName();
+ } else if(!_indexes.isEmpty()) {
+ List<String> names = new ArrayList<String>(_indexes.size());
+ for(Index idx : _indexes) {
+ names.add(idx.getName());
+ }
+ _name = names.toString();
+ } else {
+ _name = String.valueOf(_number);
+ }
+ }
+ return _name;
+ }
+
public TableImpl getTable() {
return _table;
}
// also, keep track of whether or not this is a primary key index
_primaryKey |= index.isPrimaryKey();
}
+
+ // force name to be regenerated
+ _name = null;
}
public byte getIndexFlags() {
return _rootPageNumber;
}
- private void setUnsupportedReason(String reason) {
- _unsupportedReason = reason;
- LOG.warn(reason + ", making read-only");
+ private void setUnsupportedReason(String reason, ColumnImpl col) {
+ _unsupportedReason = withErrorContext(reason);
+ if(!col.getTable().isSystem()) {
+ LOG.warn(_unsupportedReason + ", making read-only");
+ } else {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(_unsupportedReason + ", making read-only");
+ }
+ }
}
String getUnsupportedReason() {
}
}
if(idxCol == null) {
- throw new IOException("Could not find column with number "
- + columnNumber + " for index");
+ throw new IOException(withErrorContext(
+ "Could not find column with number "
+ + columnNumber + " for index"));
}
_columns.add(newColumnDescriptor(idxCol, colFlags));
}
/**
* Writes the index row count definitions into a table definition buffer.
+ * @param creator description of the indexes to write
* @param buffer Buffer to write to
- * @param indexes List of IndexBuilders to write definitions for
*/
protected static void writeRowCountDefinitions(
TableCreator creator, ByteBuffer buffer)
/**
* Writes the index definitions into a table definition buffer.
+ * @param creator description of the indexes to write
* @param buffer Buffer to write to
- * @param indexes List of IndexBuilders to write definitions for
*/
protected static void writeDefinitions(
TableCreator creator, ByteBuffer buffer)
if(columnNumber == COLUMN_UNUSED) {
// should never happen as this is validated before
throw new IllegalArgumentException(
- "Column with name " + idxCol.getName() + " not found");
+ withErrorContext(
+ "Column with name " + idxCol.getName() + " not found",
+ creator.getDatabase(), creator.getName(), idx.getName()));
}
}
return change;
}
if(isBackingPrimaryKey() && (nullCount > 0)) {
- throw new ConstraintViolationException(
+ throw new ConstraintViolationException(withErrorContext(
"Null value found in row " + Arrays.asList(row) +
- " for primary key index " + this);
+ " for primary key index"));
}
// make sure we've parsed the entries
((prevPos != null) &&
newEntry.equalsEntryBytes(prevPos.getEntry())));
if(isUnique() && !isNullEntry && isDupeEntry) {
- throw new ConstraintViolationException(
+ throw new ConstraintViolationException(withErrorContext(
"New row " + Arrays.asList(row) +
- " violates uniqueness constraint for index " + this);
+ " violates uniqueness constraint for index"));
}
change.setAddRow(newEntry, dataPage, idx, isDupeEntry);
}
++_modCount;
} else {
- LOG.warn("Added duplicate index entry " + oldEntry);
+ LOG.warn(withErrorContext("Added duplicate index entry " + oldEntry));
}
}
if(removedEntry != null) {
++_modCount;
} else {
- LOG.warn("Failed removing index entry " + oldEntry + " for row: " +
- Arrays.asList(row));
+ LOG.warn(withErrorContext(
+ "Failed removing index entry " + oldEntry + " for row: " +
+ Arrays.asList(row)));
}
return removedEntry;
}
public Object[] constructIndexRowFromEntry(Object... values)
{
if(values.length != _columns.size()) {
- throw new IllegalArgumentException(
+ throw new IllegalArgumentException(withErrorContext(
"Wrong number of column values given " + values.length +
- ", expected " + _columns.size());
+ ", expected " + _columns.size()));
}
int valIdx = 0;
Object[] idxRow = new Object[getTable().getColumnCount()];
throws IOException
{
if(dataPage.getCompressedEntrySize() > _maxPageEntrySize) {
- throw new IllegalStateException("data page is too large");
+ throw new IllegalStateException(withErrorContext("data page is too large"));
}
ByteBuffer buffer = _indexBufferH.getPageBuffer(getPageChannel());
Entry entry = newEntry(curEntryBuffer, curEntryLen, isLeaf);
if(prevEntry.compareTo(entry) >= 0) {
- throw new IOException("Unexpected order in index entries, " +
- prevEntry + " >= " + entry);
+ throw new IOException(withErrorContext(
+ "Unexpected order in index entries, " +
+ prevEntry + " >= " + entry));
}
entries.add(entry);
/**
* Determines if the given index page is a leaf or node page.
*/
- private static boolean isLeafPage(ByteBuffer buffer)
+ private boolean isLeafPage(ByteBuffer buffer)
throws IOException
{
byte pageType = buffer.get(0);
} else if(pageType == PageTypes.INDEX_NODE) {
return false;
}
- throw new IOException("Unexpected page type " + pageType);
+ throw new IOException(withErrorContext("Unexpected page type " + pageType));
}
/**
}
// unsupported sort order
setUnsupportedReason("unsupported collating sort order " + sortOrder +
- " for text index");
+ " for text index", col);
return new ReadOnlyColumnDescriptor(col, flags);
case INT:
case LONG:
default:
// we can't modify this index at this point in time
setUnsupportedReason("unsupported data type " + col.getType() +
- " for index");
+ " for index", col);
return new ReadOnlyColumnDescriptor(col, flags);
}
}
/**
* Returns the EntryType based on the given entry info.
*/
- private static EntryType determineEntryType(byte[] entryBytes,
- RowIdImpl rowId)
+ private static EntryType determineEntryType(byte[] entryBytes, RowIdImpl rowId)
{
if(entryBytes != null) {
return ((rowId.getType() == RowIdImpl.Type.NORMAL) ?
int entryMaskSize = (format.SIZE_INDEX_ENTRY_MASK * 8);
return Math.min(pageDataSize, entryMaskSize);
}
+
+ String withErrorContext(String msg) {
+ return withErrorContext(msg, getTable().getDatabase(), getTable().getName(),
+ getName());
+ }
+
+ private static String withErrorContext(String msg, DatabaseImpl db,
+ String tableName, String idxName) {
+ return msg + " (Db=" + db.getName() + ";Table=" + tableName +
+ ";Index=" + idxName + ")";
+ }
/**
* Information about the columns in an index. Also encodes new index
} else if(_lastPos.equalsEntry(entry)) {
return _lastPos;
} else {
- throw new IllegalArgumentException("Invalid entry given " + entry);
+ throw new IllegalArgumentException(
+ withErrorContext("Invalid entry given " + entry));
}
}
_reference.getOtherTablePageNumber());
if(refTable == null) {
- throw new IOException("Reference to missing table " +
- _reference.getOtherTablePageNumber());
+ throw new IOException(withErrorContext(
+ "Reference to missing table " + _reference.getOtherTablePageNumber()));
}
IndexImpl refIndex = null;
}
if(refIndex == null) {
- throw new IOException("Reference to missing index " + idxNumber +
- " on table " + refTable.getName());
+ throw new IOException(withErrorContext(
+ "Reference to missing index " + idxNumber +
+ " on table " + refTable.getName()));
}
// finally verify that we found the expected index (should reference this
(otherRef.getOtherTablePageNumber() !=
getTable().getTableDefPageNumber()) ||
(otherRef.getOtherIndexNumber() != _indexNumber)) {
- throw new IOException("Found unexpected index " + refIndex.getName() +
- " on table " + refTable.getName() +
- " with reference " + otherRef);
+ throw new IOException(withErrorContext(
+ "Found unexpected index " + refIndex.getName() +
+ " on table " + refTable.getName() + " with reference " + otherRef));
}
return refIndex;
/**
* Writes the logical index definitions into a table definition buffer.
+ * @param creator description of the indexes to write
* @param buffer Buffer to write to
- * @param indexes List of IndexBuilders to write definitions for
*/
protected static void writeDefinitions(
TableCreator creator, ByteBuffer buffer)
}
}
+ private String withErrorContext(String msg) {
+ return withErrorContext(msg, getTable().getDatabase(), getName());
+ }
+
+ private static String withErrorContext(String msg, DatabaseImpl db,
+ String idxName) {
+ return msg + " (Db=" + db.getName() + ";Index=" + idxName + ")";
+ }
+
+
/**
* Information about a foreign key reference defined in an index (when
* referential integrity should be enforced).
{
for(CacheDataPage cacheDataPage : _modifiedPages) {
if(cacheDataPage._extra._entryView.isEmpty()) {
- throw new IllegalStateException("Unexpected empty page " +
- cacheDataPage);
+ throw new IllegalStateException(withErrorContext(
+ "Unexpected empty page " + cacheDataPage));
}
writeDataPage(cacheDataPage);
}
break;
}
default:
- throw new RuntimeException("unknown update type " + upType);
+ throw new RuntimeException(withErrorContext(
+ "unknown update type " + upType));
}
boolean updateLast = (oldLastEntry != dpExtra._entryView.getLast());
DataPageExtra dpExtra = cacheDataPage._extra;
if(dpMain.hasChildTail()) {
- throw new IllegalStateException("Still has child tail?");
+ throw new IllegalStateException(withErrorContext("Still has child tail?"));
}
if(dpExtra._totalEntrySize != 0) {
- throw new IllegalStateException("Empty page but size is not 0? " +
- dpExtra._totalEntrySize + ", " +
- cacheDataPage);
+ throw new IllegalStateException(withErrorContext(
+ "Empty page but size is not 0? " + dpExtra._totalEntrySize + ", " +
+ cacheDataPage));
}
if(dpMain.isRoot()) {
break;
default:
- throw new RuntimeException("unknown update type " + upType);
+ throw new RuntimeException(withErrorContext(
+ "unknown update type " + upType));
}
if(idx < 0) {
if(expectFound) {
- throw new IllegalStateException(
+ throw new IllegalStateException(withErrorContext(
"Could not find child entry in parent; childEntry " + oldEntry +
- "; parent " + parentDataPage);
+ "; parent " + parentDataPage));
}
idx = missingIndexToInsertionPoint(idx);
} else {
if(!expectFound) {
- throw new IllegalStateException(
+ throw new IllegalStateException(withErrorContext(
"Unexpectedly found child entry in parent; childEntry " +
- newEntry + "; parent " + parentDataPage);
+ newEntry + "; parent " + parentDataPage));
}
}
updateEntry(parentDataPage, idx, newEntry, upType);
* @throws IllegalStateException if the entry type does not match the page
* type
*/
- private static void validateEntryForPage(DataPageMain dpMain, Entry entry) {
+ private void validateEntryForPage(DataPageMain dpMain, Entry entry) {
if(dpMain._leaf != entry.isLeafEntry()) {
- throw new IllegalStateException(
+ throw new IllegalStateException(withErrorContext(
"Trying to update page with wrong entry type; pageLeaf " +
- dpMain._leaf + ", entryLeaf " + entry.isLeafEntry());
+ dpMain._leaf + ", entryLeaf " + entry.isLeafEntry()));
}
}
int numEntries = origExtra._entries.size();
if(numEntries < 2) {
- throw new IllegalStateException(
- "Cannot split page with less than 2 entries " + origDataPage);
+ throw new IllegalStateException(withErrorContext(
+ "Cannot split page with less than 2 entries " + origDataPage));
}
if(origMain.isRoot()) {
DataPageExtra rootExtra = rootDataPage._extra;
if(!rootMain.isRoot()) {
- throw new IllegalArgumentException("should be called with root, duh");
+ throw new IllegalArgumentException(withErrorContext(
+ "should be called with root, duh"));
}
CacheDataPage newDataPage =
*
* @param dpExtra the entries to validate
*/
- private static void validateEntries(DataPageExtra dpExtra) throws IOException {
+ private void validateEntries(DataPageExtra dpExtra) throws IOException {
int entrySize = 0;
Entry prevEntry = IndexData.FIRST_ENTRY;
for(Entry e : dpExtra._entries) {
entrySize += e.size();
if(prevEntry.compareTo(e) >= 0) {
- throw new IOException("Unexpected order in index entries, " +
- prevEntry + " >= " + e);
+ throw new IOException(withErrorContext(
+ "Unexpected order in index entries, " + prevEntry + " >= " + e));
}
prevEntry = e;
}
if(entrySize != dpExtra._totalEntrySize) {
- throw new IllegalStateException("Expected size " + entrySize +
- " but was " + dpExtra._totalEntrySize);
+ throw new IllegalStateException(withErrorContext(
+ "Expected size " + entrySize +
+ " but was " + dpExtra._totalEntrySize));
}
}
int childTailPageNumber = dpMain._childTailPageNumber;
if(dpMain._leaf) {
if(childTailPageNumber != INVALID_INDEX_PAGE_NUMBER) {
- throw new IllegalStateException("Leaf page has tail " + dpMain);
+ throw new IllegalStateException(withErrorContext(
+ "Leaf page has tail " + dpMain));
}
return;
}
if((dpExtra._entryView.size() == 1) && dpMain.hasChildTail()) {
- throw new IllegalStateException("Single child is tail " + dpMain);
+ throw new IllegalStateException(withErrorContext(
+ "Single child is tail " + dpMain));
}
for(Entry e : dpExtra._entryView) {
validateEntryForPage(dpMain, e);
if(childMain != null) {
if(childMain._parentPageNumber != null) {
if(childMain._parentPageNumber != dpMain._pageNumber) {
- throw new IllegalStateException("Child's parent is incorrect " +
- childMain);
+ throw new IllegalStateException(withErrorContext(
+ "Child's parent is incorrect " + childMain));
}
- boolean expectTail = ((int)subPageNumber == childTailPageNumber);
+ boolean expectTail = (subPageNumber == childTailPageNumber);
if(expectTail != childMain._tail) {
- throw new IllegalStateException("Child tail status incorrect " +
- childMain);
+ throw new IllegalStateException(withErrorContext(
+ "Child tail status incorrect " + childMain));
}
}
Entry lastEntry = childMain.getExtra()._entryView.getLast();
if(e.compareTo(lastEntry) != 0) {
- throw new IllegalStateException("Invalid entry " + e +
- " but child is " + lastEntry);
+ throw new IllegalStateException(withErrorContext(
+ "Invalid entry " + e + " but child is " + lastEntry));
}
}
}
private void validatePeers(DataPageMain dpMain) throws IOException {
DataPageMain prevMain = _dataPages.get(dpMain._prevPageNumber);
if(prevMain != null) {
- if((int)prevMain._nextPageNumber != dpMain._pageNumber) {
- throw new IllegalStateException("Prev page " + prevMain +
- " does not ref " + dpMain);
+ if(prevMain._nextPageNumber != dpMain._pageNumber) {
+ throw new IllegalStateException(withErrorContext(
+ "Prev page " + prevMain + " does not ref " + dpMain));
}
validatePeerStatus(dpMain, prevMain);
}
DataPageMain nextMain = _dataPages.get(dpMain._nextPageNumber);
if(nextMain != null) {
- if((int)nextMain._prevPageNumber != dpMain._pageNumber) {
- throw new IllegalStateException("Next page " + nextMain +
- " does not ref " + dpMain);
+ if(nextMain._prevPageNumber != dpMain._pageNumber) {
+ throw new IllegalStateException(withErrorContext(
+ "Next page " + nextMain + " does not ref " + dpMain));
}
validatePeerStatus(dpMain, nextMain);
}
* @param dpMain the index page
* @param peerMain the peer index page
*/
- private static void validatePeerStatus(DataPageMain dpMain, DataPageMain peerMain)
+ private void validatePeerStatus(DataPageMain dpMain, DataPageMain peerMain)
throws IOException
{
if(dpMain._leaf != peerMain._leaf) {
- throw new IllegalStateException("Mismatched peer status " +
- dpMain._leaf + " " + peerMain._leaf);
+ throw new IllegalStateException(withErrorContext(
+ "Mismatched peer status " + dpMain._leaf + " " + peerMain._leaf));
}
if(!dpMain._leaf) {
if((dpMain._parentPageNumber != null) &&
(peerMain._parentPageNumber != null) &&
((int)dpMain._parentPageNumber != (int)peerMain._parentPageNumber)) {
- throw new IllegalStateException("Mismatched node parents " +
- dpMain._parentPageNumber + " " +
- peerMain._parentPageNumber);
+ throw new IllegalStateException(withErrorContext(
+ "Mismatched node parents " + dpMain._parentPageNumber + " " +
+ peerMain._parentPageNumber));
}
}
}
/**
* Collects all the cache pages in the cache.
*
- * @param paages the List to update
+ * @param pages the List to update
* @param dpMain the index page to collect
*/
private List<Object> collectPages(List<Object> pages, DataPageMain dpMain) {
return sb.toString();
}
+ private String withErrorContext(String msg) {
+ return _indexData.withErrorContext(msg);
+ }
+
+
/**
* Keeps track of the main info for an index page.
*/
}
public boolean hasChildTail() {
- return((int)_childTailPageNumber != INVALID_INDEX_PAGE_NUMBER);
+ return(_childTailPageNumber != INVALID_INDEX_PAGE_NUMBER);
}
public boolean isChildTailPageNumber(int pageNumber) {
- return((int)_childTailPageNumber == pageNumber);
+ return(_childTailPageNumber == pageNumber);
}
public DataPageMain getParentPage() throws IOException
// pages along the path
findCacheDataPage(getExtra()._entryView.getLast());
if(_parentPageNumber == null) {
- throw new IllegalStateException("Parent was not resolved");
+ throw new IllegalStateException(withErrorContext(
+ "Parent was not resolved"));
}
}
}
}
return null;
default:
- throw new RuntimeException("unexpected var length, long value type: " +
- getType());
+ throw new RuntimeException(withErrorContext(
+ "unexpected var length, long value type: " + getType()));
}
}
obj = encodeTextValue(obj, 0, getMaxLengthInUnits(), false).array();
break;
default:
- throw new RuntimeException("unexpected var length, long value type: " +
- getType());
+ throw new RuntimeException(withErrorContext(
+ "unexpected var length, long value type: " + getType()));
}
// create long value buffer
int rowLen = def.remaining();
if(rowLen < length) {
// warn the caller, but return whatever we can
- LOG.warn(getName() + " value may be truncated: expected length " +
- length + " found " + rowLen);
+ LOG.warn(withErrorContext(
+ "Value may be truncated: expected length " +
+ length + " found " + rowLen));
rtn = new byte[rowLen];
}
// long value on other page(s)
if (lvalDefinition.length != getFormat().SIZE_LONG_VALUE_DEF) {
- throw new IOException("Expected " + getFormat().SIZE_LONG_VALUE_DEF +
- " bytes in long value definition, but found " +
- lvalDefinition.length);
+ throw new IOException(withErrorContext(
+ "Expected " + getFormat().SIZE_LONG_VALUE_DEF +
+ " bytes in long value definition, but found " +
+ lvalDefinition.length));
}
int rowNum = ByteUtil.getUnsignedByte(def);
int rowLen = rowEnd - rowStart;
if(rowLen < length) {
// warn the caller, but return whatever we can
- LOG.warn(getName() + " value may be truncated: expected length " +
- length + " found " + rowLen);
+ LOG.warn(withErrorContext(
+ "Value may be truncated: expected length " +
+ length + " found " + rowLen));
rtn = new byte[rowLen];
}
break;
default:
- throw new IOException("Unrecognized long value type: " + type);
+ throw new IOException(withErrorContext(
+ "Unrecognized long value type: " + type));
}
}
throws IOException
{
if(value.length > getType().getMaxSize()) {
- throw new IOException("value too big for column, max " +
- getType().getMaxSize() + ", got " +
- value.length);
+ throw new IOException(withErrorContext(
+ "value too big for column, max " +
+ getType().getMaxSize() + ", got " + value.length));
}
// determine which type to write
break;
default:
- throw new IOException("Unrecognized long value type: " + type);
+ throw new IOException(withErrorContext(
+ "Unrecognized long value type: " + type));
}
// update def
Collections.<IndexBuilder>emptyList());
}
+ public String getName() {
+ return _name;
+ }
+
+ public DatabaseImpl getDatabase() {
+ return _database;
+ }
+
public JetFormat getFormat() {
return _database.getFormat();
}
colOwnedPages = null;
colFreeSpacePages = null;
tableBuffer.position(pos + 8);
- LOG.warn("Table " + _name + " invalid column " + umapColNum +
- " usage map definition: " + e);
+ LOG.warn(withErrorContext("Invalid column " + umapColNum +
+ " usage map definition: " + e));
}
for(ColumnImpl col : _columns) {
return column;
}
}
- throw new IllegalArgumentException("Column with name " + name +
- " does not exist in this table");
+ throw new IllegalArgumentException(withErrorContext(
+ "Column with name " + name + " does not exist in this table"));
}
public boolean hasColumn(String name) {
return index;
}
}
- throw new IllegalArgumentException("Index with name " + name +
- " does not exist on this table");
+ throw new IllegalArgumentException(withErrorContext(
+ "Index with name " + name + " does not exist on this table"));
}
public IndexImpl getPrimaryKeyIndex() {
return index;
}
}
- throw new IllegalArgumentException("Table " + getName() +
- " does not have a primary key index");
+ throw new IllegalArgumentException(withErrorContext(
+ "No primary key index found"));
}
public IndexImpl getForeignKeyIndex(Table otherTable) {
return index;
}
}
- throw new IllegalArgumentException(
- "Table " + getName() + " does not have a foreign key reference to " +
- otherTable.getName());
+ throw new IllegalArgumentException(withErrorContext(
+ "No foreign key reference to " +
+ otherTable.getName() + " found"));
}
/**
throws IOException
{
if(this != column.getTable()) {
- throw new IllegalArgumentException(
- "Given column " + column + " is not from this table");
+ throw new IllegalArgumentException(withErrorContext(
+ "Given column " + column + " is not from this table"));
}
requireValidRowId(rowId);
if (overflowRow) {
if((rowEnd - rowStart) < 4) {
- throw new IOException("invalid overflow row info");
+ throw new IOException(rowState.getTable().withErrorContext(
+ "invalid overflow row info"));
}
// Overflow page. the "row" data in the current page points to
int rowSize = rowData.remaining();
if (rowSize > getFormat().MAX_ROW_SIZE) {
- throw new IOException("Row size " + rowSize + " is too large");
+ throw new IOException(withErrorContext(
+ "Row size " + rowSize + " is too large"));
}
// get page with space
// corruption (failed write vs. a row failure which was not a
// write failure). we don't know the status of any rows at this
// point (and the original failure is probably irrelevant)
- LOG.warn("Secondary row failure which preceded the write failure",
+ LOG.warn(withErrorContext(
+ "Secondary row failure which preceded the write failure"),
rowWriteFailure);
updateCount = 0;
rowWriteFailure = flushFailure;
}
}
- throw new BatchUpdateException(updateCount, rowWriteFailure);
+ throw new BatchUpdateException(
+ updateCount, withErrorContext("Failed adding rows"),
+ rowWriteFailure);
}
} finally {
keepRawVarValues);
if (newRowData.limit() > getFormat().MAX_ROW_SIZE) {
- throw new IOException("Row size " + newRowData.limit() +
- " is too large");
+ throw new IOException(withErrorContext(
+ "Row size " + newRowData.limit() + " is too large"));
}
if(!_indexDatas.isEmpty()) {
/**
* @throws IllegalStateException if the given rowId is invalid
*/
- private static void requireValidRowId(RowIdImpl rowId) {
+ private void requireValidRowId(RowIdImpl rowId) {
if(!rowId.isValid()) {
- throw new IllegalArgumentException("Given rowId is invalid: " + rowId);
+ throw new IllegalArgumentException(withErrorContext(
+ "Given rowId is invalid: " + rowId));
}
}
/**
* @throws IllegalStateException if the given row is invalid or deleted
*/
- private static void requireNonDeletedRow(RowState rowState, RowIdImpl rowId)
+ private void requireNonDeletedRow(RowState rowState, RowIdImpl rowId)
{
if(!rowState.isValid()) {
- throw new IllegalArgumentException(
- "Given rowId is invalid for this table: " + rowId);
+ throw new IllegalArgumentException(withErrorContext(
+ "Given rowId is invalid for this table: " + rowId));
}
if(rowState.isDeleted()) {
- throw new IllegalStateException("Row is deleted: " + rowId);
+ throw new IllegalStateException(withErrorContext(
+ "Row is deleted: " + rowId));
}
}
return copy;
}
+ private String withErrorContext(String msg) {
+ return withErrorContext(msg, getDatabase(), getName());
+ }
+
+ private static String withErrorContext(String msg, DatabaseImpl db,
+ String tableName) {
+ return msg + " (Db=" + db.getName() + ";Table=" + tableName + ")";
+ }
+
/** various statuses for the row data */
private enum RowStatus {
INIT, INVALID_PAGE, INVALID_ROW, VALID, DELETED, NORMAL, OVERFLOW;
// this should never see modifications because it only happens within
// the positionAtRowData method
if(!isUpToDate()) {
- throw new IllegalStateException("Table modified while searching?");
+ throw new IllegalStateException(getTable().withErrorContext(
+ "Table modified while searching?"));
}
if(_rowStatus != RowStatus.OVERFLOW) {
- throw new IllegalStateException("Row is not an overflow row?");
+ throw new IllegalStateException(getTable().withErrorContext(
+ "Row is not an overflow row?"));
}
_finalRowId = rowId;
_finalRowBuffer = _overflowRowBufferH.setPage(getPageChannel(),
short foundType = getShortValue(getQueryType(rows),
_type.getValue());
if(foundType != _type.getValue()) {
- throw new IllegalStateException("Unexpected query type " + foundType);
+ throw new IllegalStateException(withErrorContext(
+ "Unexpected query type " + foundType));
}
}
}
@Override protected void format(StringBuilder builder, Row row) {
String typeName = PARAM_TYPE_MAP.get(row.flag);
if(typeName == null) {
- throw new IllegalStateException("Unknown param type " + row.flag);
+ throw new IllegalStateException(withErrorContext(
+ "Unknown param type " + row.flag));
}
builder.append(row.name1).append(' ').append(typeName);
Join toExpr = getJoinExpr(toTable, joinExprs);
String joinType = JOIN_TYPE_MAP.get(join.flag);
if(joinType == null) {
- throw new IllegalStateException("Unknown join type " + join.flag);
+ throw new IllegalStateException(withErrorContext(
+ "Unknown join type " + join.flag));
}
String expr = new StringBuilder().append(fromExpr)
return result;
}
- private static Join getJoinExpr(String table, List<Join> joinExprs)
+ private Join getJoinExpr(String table, List<Join> joinExprs)
{
for(Iterator<Join> iter = joinExprs.iterator(); iter.hasNext(); ) {
Join joinExpr = iter.next();
return joinExpr;
}
}
- throw new IllegalStateException("Cannot find join table " + table);
+ throw new IllegalStateException(withErrorContext(
+ "Cannot find join table " + table));
}
- private static Collection<List<Row>> combineJoins(List<Row> joins)
+ private Collection<List<Row>> combineJoins(List<Row> joins)
{
// combine joins with the same to/from tables
Map<List<String>,List<Row>> comboJoinMap =
comboJoins = new ArrayList<Row>();
comboJoinMap.put(key, comboJoins);
} else {
- if((short)comboJoins.get(0).flag != join.flag) {
- throw new IllegalStateException(
- "Mismatched join flags for combo joins");
+ if(comboJoins.get(0).flag != join.flag) {
+ throw new IllegalStateException(withErrorContext(
+ "Mismatched join flags for combo joins"));
}
}
comboJoins.add(join);
return new UnionQueryImpl(name, rows, objectId, objectFlag);
default:
// unknown querytype
- throw new IllegalStateException(
- "unknown query object flag " + typeFlag);
+ throw new IllegalStateException(withErrorContext(
+ "unknown query object flag " + typeFlag, name));
}
} catch(IllegalStateException e) {
- LOG.warn("Failed parsing query", e);
+ LOG.warn(withErrorContext("Failed parsing query", name), e);
}
// return unknown query
return new UnknownQueryImpl(name, rows, objectId, objectFlag);
}
- private static Short getQueryType(List<Row> rows)
+ private Short getQueryType(List<Row> rows)
{
return getUniqueRow(getRowsByAttribute(rows, TYPE_ATTRIBUTE)).flag;
}
return result;
}
- protected static Row getUniqueRow(List<Row> rows) {
+ protected Row getUniqueRow(List<Row> rows) {
if(rows.size() == 1) {
return rows.get(0);
}
if(rows.isEmpty()) {
return EMPTY_ROW;
}
- throw new IllegalStateException("Unexpected number of rows for" + rows);
+ throw new IllegalStateException(withErrorContext(
+ "Unexpected number of rows for" + rows));
}
protected static List<Row> filterRowsByFlag(
return builder;
}
+ private String withErrorContext(String msg) {
+ return withErrorContext(msg, getName());
+ }
+
+ private static String withErrorContext(String msg, String queryName) {
+ return msg + " (Query: " + queryName + ")";
+ }
+
+
private static final class UnknownQueryImpl extends QueryImpl
{
private UnknownQueryImpl(String name, List<Row> rows, int objectId,
import com.healthmarketscience.jackcess.IndexCursor;
import com.healthmarketscience.jackcess.Row;
import com.healthmarketscience.jackcess.Table;
+import com.healthmarketscience.jackcess.impl.DatabaseImpl;
import com.healthmarketscience.jackcess.impl.IndexImpl;
/**
for(int i = 1; i < toCols.size(); ++i) {
sb.append(",").append(toCols.get(i).getName());
}
- sb.append(toType);
+ sb.append(toType)
+ .append(" (Db=")
+ .append(((DatabaseImpl)getFromTable().getDatabase()).getName())
+ .append(")");
return sb.toString();
}