1 5 package org.h2.server.web; 6 7 import java.util.HashMap ; 8 import java.util.HashSet ; 9 import java.util.Iterator ; 10 import java.util.Map ; 11 import java.util.Map.Entry; 12 13 import org.h2.bnf.Bnf; 14 import org.h2.bnf.Rule; 15 import org.h2.bnf.Sentence; 16 import org.h2.command.Parser; 17 import org.h2.message.Message; 18 import org.h2.util.StringUtils; 19 20 public class DbContextRule implements Rule { 21 DbContents contents; 22 int type; 23 static final int COLUMN = 0, TABLE = 1, TABLE_ALIAS = 2; 24 public static final int NEW_TABLE_ALIAS = 3; 25 public static final int COLUMN_ALIAS = 4; 26 private static boolean SUGGEST_TABLE_ALIAS; 27 28 DbContextRule(DbContents contents, int type) { 29 this.contents = contents; 30 this.type = type; 31 } 32 33 public String name() { 34 return null; 35 } 36 37 public String random(Bnf config, int level) { 38 return null; 39 } 40 41 public Rule last() { 42 return this; 43 } 44 45 public void setLinks(HashMap ruleMap) { 46 } 47 48 public void addNextTokenList(String query, Sentence sentence) { 49 switch(type) { 50 case TABLE: 51 addTable(query, sentence); 52 break; 53 case NEW_TABLE_ALIAS: 54 addNewTableAlias(query, sentence); 55 break; 56 case TABLE_ALIAS: 57 addTableAlias(query, sentence); 58 break; 59 case COLUMN_ALIAS: 60 case COLUMN: 63 addColumn(query, sentence); 64 break; 65 } 66 } 67 68 private void addTableAlias(String query, Sentence sentence) { 69 String q = StringUtils.toUpperEnglish(query.trim()); 70 HashMap map = sentence.getAliases(); 71 HashSet set = new HashSet (); 72 if(map != null) { 73 for(Iterator it = map.entrySet().iterator(); it.hasNext();) { 74 Map.Entry entry = (Entry) it.next(); 75 String alias = (String ) entry.getKey(); 76 DbTableOrView table = (DbTableOrView) entry.getValue(); 77 set.add(StringUtils.toUpperEnglish(table.name)); 78 if(q.length()==0 || alias.startsWith(q)) { 79 if(q.length() < alias.length()) { 80 sentence.add(alias + ".", alias.substring(q.length()) + ".", Sentence.CONTEXT); 81 } 82 } 83 } 84 } 85 HashSet tables = sentence.getTables(); 86 if(tables != null) { 87 for(Iterator it = tables.iterator(); it.hasNext(); ) { 88 DbTableOrView table = (DbTableOrView)it.next(); 89 String tableName = StringUtils.toUpperEnglish(table.name); 90 if(!set.contains(tableName)) { 95 if(q.length()==0 || tableName.startsWith(q)) { 96 if(q.length() < tableName.length()) { 97 sentence.add(tableName + ".", tableName.substring(q.length()) + ".", Sentence.CONTEXT); 98 } 99 } 100 } 101 } 102 } 103 } 104 105 private void addNewTableAlias(String query, Sentence sentence) { 106 if(SUGGEST_TABLE_ALIAS) { 107 if (query.length() > 3) { 109 return; 110 } 111 String lastTableName = StringUtils.toUpperEnglish(sentence.getLastTable().name); 112 if (lastTableName == null) { 113 return; 114 } 115 HashMap map = sentence.getAliases(); 116 String shortName = lastTableName.substring(0, 1); 117 if (map != null && map.containsKey(shortName)) { 118 int result = 0; 119 for (int i = 1;; i++) { 120 if (!map.containsKey(shortName + i)) { 121 result = i; 122 break; 123 } 124 } 125 shortName += result; 126 } 127 String q = StringUtils.toUpperEnglish(query.trim()); 128 if (q.length() == 0 || StringUtils.toUpperEnglish(shortName).startsWith(q)) { 129 if (q.length() < shortName.length()) { 130 sentence.add(shortName, shortName.substring(q.length()), Sentence.CONTEXT); 131 } 132 } 133 } 134 } 135 136 148 private void addTable(String query, Sentence sentence) { 149 DbSchema schema = contents.defaultSchema; 150 String text = StringUtils.toUpperEnglish(sentence.text).trim(); 151 if(text.endsWith(".")) { 152 for(int i=0; i<contents.schemas.length; i++) { 153 if(text.endsWith(StringUtils.toUpperEnglish(contents.schemas[i].name)+".")) { 154 schema = contents.schemas[i]; 155 break; 156 } 157 } 158 } 159 String q = StringUtils.toUpperEnglish(query.trim()); 160 DbTableOrView[] tables = schema.tables; 161 for(int i=0; i<tables.length; i++) { 162 DbTableOrView table = tables[i]; 163 if(q.length()==0 || StringUtils.toUpperEnglish(table.name).startsWith(q)) { 164 if(q.length() < table.quotedName.length()) { 165 sentence.add(table.quotedName, table.quotedName.substring(q.length()), Sentence.CONTEXT); 166 } 167 } 168 } 169 } 170 171 private void addColumn(String query, Sentence sentence) { 172 String tableName = query; 173 String columnPattern = ""; 174 if(query.trim().length()==0) { 175 tableName = null; 176 if(sentence.text.trim().endsWith(".")) { 177 return; 178 } 179 } else { 180 tableName = StringUtils.toUpperEnglish(query.trim()); 181 if(tableName.endsWith(".")) { 182 tableName = tableName.substring(0, tableName.length()-1); 183 } else { 184 columnPattern = StringUtils.toUpperEnglish(query.trim()); 185 tableName = null; 186 } 187 } 188 HashSet set = null; 189 HashMap aliases = sentence.getAliases(); 190 if(tableName == null && sentence.getTables() != null) { 191 set = sentence.getTables(); 192 } 193 DbTableOrView table = null; 194 if(tableName != null && aliases != null && aliases.get(tableName) != null) { 195 table = (DbTableOrView) aliases.get(tableName); 196 tableName = StringUtils.toUpperEnglish(table.name); 197 } 198 if(tableName == null) { 199 if(set == null && aliases == null) { 200 return; 201 } 202 if((set != null && set.size()>1) || (aliases != null && aliases.size()>1)) { 203 return; 204 } 205 } 206 if(table == null) { 207 DbTableOrView[] tables = contents.defaultSchema.tables; 208 for(int i=0; i<tables.length; i++) { 209 DbTableOrView tab = tables[i]; 210 String t = StringUtils.toUpperEnglish(tab.name); 211 if(tableName != null && !tableName.equals(t)) { 212 continue; 213 } 214 if(set != null && !set.contains(tab)) { 215 continue; 216 } 217 table = tab; 218 break; 219 } 220 } 221 if(table != null) { 222 for(int j=0; j<table.columns.length; j++) { 223 String columnName = table.columns[j].name; 224 if(!StringUtils.toUpperEnglish(columnName).startsWith(columnPattern)) { 225 continue; 226 } 227 if(columnPattern.length() < columnName.length()) { 228 sentence.add(columnName, columnName.substring(columnPattern.length()), Sentence.CONTEXT); 229 } 230 } 231 } 232 } 233 234 public String matchRemove(String query, Sentence sentence) { 235 if(query.length()==0) { 236 return null; 237 } 238 String s; 239 switch(type) { 240 case TABLE: 241 s = matchTable(query, sentence); 242 break; 243 case NEW_TABLE_ALIAS: 244 s = matchTableAlias(query, sentence, true); 245 break; 246 case TABLE_ALIAS: 247 s = matchTableAlias(query, sentence, false); 248 break; 249 case COLUMN_ALIAS: 250 s = matchColumnAlias(query, sentence, false); 251 break; 252 case COLUMN: 253 s = matchColumn(query, sentence); 254 break; 255 default: 256 throw Message.getInternalError("type="+type); 257 } 258 return s; 259 } 260 261 public String matchTable(String query, Sentence sentence) { 262 String up = StringUtils.toUpperEnglish(query); 263 DbTableOrView[] tables = contents.defaultSchema.tables; 264 String best = null; 265 DbTableOrView bestTable = null; 266 for(int i=0; i<tables.length; i++) { 267 DbTableOrView table = tables[i]; 268 String tableName = StringUtils.toUpperEnglish(table.name); 269 if(up.startsWith(tableName)) { 270 if(best == null || tableName.length() > best.length()) { 271 best = tableName; 272 bestTable = table; 273 } 274 } 275 } 276 if(best == null) { 277 return null; 278 } 279 sentence.addTable(bestTable); 280 query = query.substring(best.length()); 281 return query; 285 } 286 287 public String matchColumnAlias(String query, Sentence sentence, boolean add) { 288 String up = StringUtils.toUpperEnglish(query); 289 int i=0; 290 if(query.indexOf(' ')<0) { 291 return null; 292 } 293 for(; i<up.length(); i++) { 294 char ch = up.charAt(i); 295 if(ch != '_' && !Character.isLetterOrDigit(ch)) { 296 break; 297 } 298 } 299 if(i==0) { 300 return null; 301 } 302 String alias = up.substring(0, i); 303 if(Parser.isKeyword(alias)) { 304 return null; 305 } 306 return query.substring(alias.length()); 307 } 308 309 public String matchTableAlias(String query, Sentence sentence, boolean add) { 310 String up = StringUtils.toUpperEnglish(query); 311 int i=0; 312 if(query.indexOf(' ')<0) { 313 return null; 314 } 315 for(; i<up.length(); i++) { 316 char ch = up.charAt(i); 317 if(ch != '_' && !Character.isLetterOrDigit(ch)) { 318 break; 319 } 320 } 321 if(i==0) { 322 return null; 323 } 324 String alias = up.substring(0, i); 325 if(Parser.isKeyword(alias)) { 326 return null; 327 } 328 if(add) { 329 sentence.addAlias(alias, sentence.getLastTable()); 330 } 331 HashMap map = sentence.getAliases(); 332 if((map != null && map.containsKey(alias)) || (sentence.getLastTable() == null)) { 333 if(add && query.length() == alias.length()) { 334 return query; 335 } 336 query = query.substring(alias.length()); 337 return query; 338 } else { 339 HashSet tables = sentence.getTables(); 340 if(tables != null) { 341 String best = null; 342 for(Iterator it = tables.iterator(); it.hasNext(); ) { 343 DbTableOrView table = (DbTableOrView)it.next(); 344 String tableName = StringUtils.toUpperEnglish(table.name); 345 if(alias.startsWith(tableName) && (best==null || tableName.length()>best.length())) { 350 best = tableName; 351 } 352 } 353 if(best != null) { 354 query = query.substring(best.length()); 355 return query; 356 } 357 } 358 return null; 359 } 360 } 361 362 public String matchColumn(String query, Sentence sentence) { 363 String up = StringUtils.toUpperEnglish(query); 364 HashSet set = sentence.getTables(); 365 DbTableOrView[] tables = contents.defaultSchema.tables; 366 String best = null; 367 for(int i=0; i<tables.length; i++) { 368 DbTableOrView table = tables[i]; 369 if(set != null && !set.contains(table)) { 370 continue; 371 } 372 for(int j=0; j<table.columns.length; j++) { 373 String name = StringUtils.toUpperEnglish(table.columns[j].name); 374 if(up.startsWith(name)) { 375 String b = query.substring(name.length()); 376 if(best == null || b.length() < best.length()) { 377 best = b; 378 } 379 } 380 } 381 } 382 return best; 383 } 384 } 385 | Popular Tags |