1 10 package org.mmbase.storage.search.implementation.database.informix.excalibur; 11 12 import java.io.*; 13 import java.util.*; 14 15 import org.mmbase.bridge.Field; 16 import org.mmbase.module.core.*; 17 import org.mmbase.storage.StorageManagerFactory; 18 import org.mmbase.storage.search.*; 19 import org.mmbase.storage.search.implementation.database.*; 20 import org.mmbase.util.logging.*; 21 import org.w3c.dom.*; 22 import org.xml.sax.*; 23 24 42 public class EtxSqlHandler extends ChainedSqlHandler implements SqlHandler { 44 45 46 private static Logger log 47 = Logging.getLoggerInstance(EtxSqlHandler.class.getName()); 48 49 53 private Set indexedFields = new HashSet(); 54 55 60 public EtxSqlHandler(SqlHandler successor) throws IOException { 61 super(successor); 62 init(); 63 } 64 65 public void appendConstraintToSql(StringBuffer sb, Constraint constraint, 67 SearchQuery query, boolean inverse, boolean inComposite) 68 throws SearchQueryException { 69 boolean overallInverse = inverse ^ constraint.isInverse(); 71 72 if (constraint instanceof StringSearchConstraint) { 73 StringSearchConstraint stringSearchConstraint 76 = (StringSearchConstraint) constraint; 77 StepField field = stringSearchConstraint.getField(); 78 Map parameters = stringSearchConstraint.getParameters(); 79 80 if (overallInverse) { 83 sb.append("NOT "); 84 } 85 sb.append("etx_contains("). 86 append(getAllowedValue(field.getStep().getAlias())). 87 append("."). 88 append(getAllowedValue(field.getFieldName())). 89 append(", Row('"); 90 91 Iterator iSearchTerms 92 = stringSearchConstraint.getSearchTerms().iterator(); 93 while (iSearchTerms.hasNext()) { 94 String searchTerm = (String ) iSearchTerms.next(); 95 sb.append(searchTerm); 96 if (iSearchTerms.hasNext()) { 97 sb.append(" "); 98 } 99 } 100 sb.append("', '"); 101 switch (stringSearchConstraint.getSearchType()) { 102 case StringSearchConstraint.SEARCH_TYPE_WORD_ORIENTED: 103 sb.append("SEARCH_TYPE = WORD"); 104 break; 105 106 case StringSearchConstraint.SEARCH_TYPE_PHRASE_ORIENTED: 107 sb.append("SEARCH_TYPE = PHRASE_EXACT"); 108 break; 109 110 case StringSearchConstraint.SEARCH_TYPE_PROXIMITY_ORIENTED: 111 Integer proximityLimit 112 = (Integer ) parameters. 113 get(StringSearchConstraint.PARAM_PROXIMITY_LIMIT); 114 if (proximityLimit == null) { 115 throw new IllegalStateException ( 116 "Parameter PARAM_PROXIMITY_LIMIT not set " + 117 "while trying to perform proximity oriented search."); 118 } 119 sb.append("SEARCH_TYPE = PROX_SEARCH(").append(proximityLimit).append(")"); 120 break; 121 122 default: 123 throw new IllegalStateException ("Invalid searchtype value: " 124 + stringSearchConstraint.getSearchType()); 125 } 126 127 switch(stringSearchConstraint.getMatchType()) { 128 case StringSearchConstraint.MATCH_TYPE_FUZZY: 129 Float fuzziness = 130 (Float ) parameters.get(StringSearchConstraint.PARAM_FUZZINESS); 131 int wordScore = Math.round(100 * fuzziness.floatValue()); 132 sb.append(" & PATTERN_ALL & WORD_SCORE = ").append(wordScore); 133 break; 134 135 case StringSearchConstraint.MATCH_TYPE_LITERAL: 136 break; 137 138 case StringSearchConstraint.MATCH_TYPE_SYNONYM: 139 log.warn("Synonym matching not supported. Executing this query with literal matching instead: " + query); 140 break; 141 142 default: 143 throw new IllegalStateException ("Invalid matchtype value: " 144 + stringSearchConstraint.getMatchType()); 145 } 146 147 sb.append("'))"); 148 149 } else { 150 getSuccessor().appendConstraintToSql(sb, constraint, query, 151 inverse, inComposite); 152 } 153 } 154 155 public int getSupportLevel(int feature, SearchQuery query) throws SearchQueryException { 157 int support; 158 switch (feature) { 159 case SearchQueryHandler.FEATURE_MAX_NUMBER: 160 Constraint constraint = query.getConstraint(); 163 if (constraint != null 164 && constraint instanceof StringSearchConstraint 165 && hasEtxIndex(((StringSearchConstraint) constraint).getField()) 166 && !hasAdditionalConstraints(query)) { 167 support=SearchQueryHandler.SUPPORT_OPTIMAL; 168 } else { 169 support = getSuccessor().getSupportLevel(feature, query); 170 } 171 break; 172 default: 173 support = getSuccessor().getSupportLevel(feature, query); 174 } 175 return support; 176 } 177 178 public int getSupportLevel(Constraint constraint, SearchQuery query) 180 throws SearchQueryException { 181 int support; 182 183 if (constraint instanceof StringSearchConstraint 184 && hasEtxIndex(((StringSearchConstraint) constraint).getField())) { 185 StringSearchConstraint stringSearchConstraint = 186 (StringSearchConstraint) constraint; 187 if (stringSearchConstraint.getMatchType() 192 == StringSearchConstraint.MATCH_TYPE_SYNONYM) { 193 support = SearchQueryHandler.SUPPORT_NONE; 194 } else if (containsOtherStringSearchConstraints( 195 query.getConstraint(), stringSearchConstraint)) { 196 support = SearchQueryHandler.SUPPORT_WEAK; 197 } else { 198 support = SearchQueryHandler.SUPPORT_OPTIMAL; 199 } 200 } else { 201 support = getSuccessor().getSupportLevel(constraint, query); 202 } 203 return support; 204 } 205 206 213 public boolean hasEtxIndex(StepField field) { 214 boolean result = false; 215 if (field.getType() == Field.TYPE_STRING 216 || field.getType() == Field.TYPE_XML) { 217 result = indexedFields.contains( 218 field.getStep().getTableName() + "." + field.getFieldName()); 219 } 220 return result; 221 } 222 223 231 protected boolean hasAdditionalConstraints(SearchQuery query) { 232 Iterator iSteps = query.getSteps().iterator(); 233 while (iSteps.hasNext()) { 234 Step step = (Step) iSteps.next(); 235 if (step instanceof RelationStep || step.getNodes().size() > 0) { 236 return true; 238 } 239 } 240 return false; 242 } 243 244 254 protected boolean containsOtherStringSearchConstraints( 255 Constraint constraint, 256 StringSearchConstraint searchConstraint) { 257 if (constraint instanceof CompositeConstraint) { 258 Iterator iChildConstraints 260 = ((CompositeConstraint) constraint).getChilds().iterator(); 261 while (iChildConstraints.hasNext()) { 262 Constraint childConstraint 263 = (Constraint) iChildConstraints.next(); 264 if (containsOtherStringSearchConstraints( 265 childConstraint, searchConstraint)) { 266 return true; 268 } 269 } 270 return false; 272 273 } else if (constraint instanceof StringSearchConstraint 274 && constraint != searchConstraint) { 275 return true; 277 278 } else { 279 return false; 281 } 282 } 283 284 294 private void init() throws IOException { 295 File etxConfigFile = new File( 296 MMBaseContext.getConfigPath() + "/databases/etxindices.xml"); 297 XmlEtxIndicesReader configReader = 298 new XmlEtxIndicesReader( 299 new InputSource( 300 new BufferedReader( 301 new FileReader(etxConfigFile)))); 302 303 for (Iterator eSbspaces = configReader.getSbspaceElements(); eSbspaces.hasNext();) { 304 Element sbspace = (Element) eSbspaces.next(); 305 306 for (Iterator eEtxIndices = configReader.getEtxindexElements(sbspace); eEtxIndices.hasNext();) { 307 Element etxIndex = (Element) eEtxIndices.next(); 308 String table = configReader.getEtxindexTable(etxIndex); 309 String field = configReader.getEtxindexField(etxIndex); 310 String index = configReader.getEtxindexValue(etxIndex); 311 try { 312 String builderField = toBuilderField(table, field); 313 indexedFields.add(builderField); 314 log.service("Registered etx index \"" + index + 315 "\" for builderfield " + builderField); 316 } catch (IllegalArgumentException e) { 317 log.error("Failed to register etx index \"" + 318 index + "\": " + e); 319 } 320 } 321 } 322 } 323 324 333 static String toBuilderField(String dbTable, String dbField) { 334 MMBase mmbase = MMBase.getMMBase(); 336 StorageManagerFactory factory = mmbase.getStorageManagerFactory(); 337 String tablePrefix = mmbase.getBaseName() + "_"; 338 339 if (!dbTable.startsWith(tablePrefix)) { 340 throw new IllegalArgumentException ( 341 "Invalid tablename: \"" + dbTable + "\". " + 342 "It should start with the prefix \"" + tablePrefix + "\"."); 343 } 344 345 String builderName = dbTable.substring(tablePrefix.length()); 346 MMObjectBuilder builder; 347 try { 348 builder = mmbase.getBuilder(builderName); 349 } catch (BuilderConfigurationException e){ 350 builder = null; 352 } 353 354 if (builder == null) { 355 throw new IllegalArgumentException ( 356 "Unknown builder: \"" + builderName + "\"."); 357 } 358 359 Iterator iFieldNames = builder.getFieldNames().iterator(); 360 while (iFieldNames.hasNext()) { 361 String fieldName = (String ) iFieldNames.next(); 362 if (factory.getStorageIdentifier(fieldName).equals(dbField)) { 363 return builderName + "." + fieldName; 364 } 365 } 366 367 throw new IllegalArgumentException ( 368 "No field corresponding to database field \"" + dbField 369 + "\" found in builder \"" + builderName + "\"."); 370 } 371 372 } 373 | Popular Tags |