From 3193d76ffd81eef6b5b743bf25132ba00861dc4b Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Wed, 31 May 2017 03:53:25 +0000 Subject: [PATCH] Fix parsing of certain internal-use queries. Fixes issue #142 git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@1102 f203690c-595d-4dc9-a70b-905162fa7fd2 --- src/changes/changes.xml | 6 ++++ .../jackcess/impl/query/QueryFormat.java | 13 +++++++- .../jackcess/impl/query/QueryImpl.java | 30 +++++++++++++++---- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index f2c0e5e..94c0767 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -4,6 +4,12 @@ Tim McCune + + + Fix parsing of certain internal-use queries (such as those used as the + data source for the fields in a form). + + Implement support for partial index lookups. Efficient IndexCursor diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/query/QueryFormat.java b/src/main/java/com/healthmarketscience/jackcess/impl/query/QueryFormat.java index 6986191..f9513d4 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/query/QueryFormat.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/query/QueryFormat.java @@ -21,6 +21,7 @@ import java.util.Map; import java.util.regex.Pattern; import com.healthmarketscience.jackcess.DataType; +import com.healthmarketscience.jackcess.query.Query; import org.apache.commons.lang.SystemUtils; /** @@ -48,7 +49,7 @@ public class QueryFormat // dbQAction = 240 // mask which removes superfluous flags from object flags - static final int OBJECT_FLAG_MASK = 0XF0; + static final int OBJECT_FLAG_MASK = 0xF0; public static final String COL_ATTRIBUTE = "Attribute"; public static final String COL_EXPRESSION = "Expression"; @@ -130,4 +131,14 @@ public class QueryFormat JOIN_TYPE_MAP.put((short)3, " RIGHT JOIN "); } + public static final Map TYPE_MAP = + new HashMap(); + static { + for(Query.Type type : Query.Type.values()) { + if(type != Query.Type.UNKNOWN) { + TYPE_MAP.put(type.getValue(), type); + } + } + } + } diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/query/QueryImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/query/QueryImpl.java index 0645a81..a9fd5e6 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/query/QueryImpl.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/query/QueryImpl.java @@ -387,9 +387,20 @@ public abstract class QueryImpl implements Query int objectId) { // remove other object flags before testing for query type - int typeFlag = objectFlag & OBJECT_FLAG_MASK; + int objTypeFlag = objectFlag & OBJECT_FLAG_MASK; + + if(objTypeFlag == 0) { + // sometimes the query rows tell a different story + short rowTypeFlag = getShortValue(getQueryType(rows), objTypeFlag); + Type rowType = TYPE_MAP.get(rowTypeFlag); + if((rowType != null) && (rowType.getObjectFlag() != objTypeFlag)) { + // use row type instead of object flag type + objTypeFlag = rowType.getObjectFlag(); + } + } + try { - switch(typeFlag) { + switch(objTypeFlag) { case SELECT_QUERY_OBJECT_FLAG: return new SelectQueryImpl(name, rows, objectId, objectFlag); case MAKE_TABLE_QUERY_OBJECT_FLAG: @@ -411,7 +422,7 @@ public abstract class QueryImpl implements Query default: // unknown querytype throw new IllegalStateException(withErrorContext( - "unknown query object flag " + typeFlag, name)); + "unknown query object flag " + objTypeFlag, name)); } } catch(IllegalStateException e) { LOG.warn(withErrorContext("Failed parsing query", name), e); @@ -421,9 +432,9 @@ public abstract class QueryImpl implements Query return new UnknownQueryImpl(name, rows, objectId, objectFlag); } - private Short getQueryType(List rows) + private static Short getQueryType(List rows) { - return getUniqueRow(getRowsByAttribute(rows, TYPE_ATTRIBUTE)).flag; + return getFirstRowByAttribute(rows, TYPE_ATTRIBUTE).flag; } private static List getRowsByAttribute(List rows, Byte attribute) { @@ -436,6 +447,15 @@ public abstract class QueryImpl implements Query return result; } + private static Row getFirstRowByAttribute(List rows, Byte attribute) { + for(Row row : rows) { + if(attribute.equals(row.attribute)) { + return row; + } + } + return EMPTY_ROW; + } + protected Row getUniqueRow(List rows) { if(rows.size() == 1) { return rows.get(0); -- 2.39.5