1 /* 2 * Copyright 2015-2018 HuntLabs.cn 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 module hunt.sql.parser.SQLSelectListCache; 17 18 import hunt.sql.ast.statement.SQLSelectQueryBlock; 19 // import entity.support.logging.Log; 20 // import entity.support.logging.LogFactory; 21 import hunt.sql.util.FnvHash; 22 import hunt.sql.parser.Lexer; 23 24 import hunt.collection; 25 import hunt.sql.parser.SQLSelectParser; 26 import hunt.sql.parser.SQLParserUtils; 27 import hunt.String; 28 import hunt.sql.parser.Token; 29 import std.algorithm.searching; 30 import hunt.logging; 31 import hunt.text; 32 33 public class SQLSelectListCache { 34 // private static Log LOG = LogFactory.getLog(SQLSelectListCache.class); 35 private string dbType; 36 private List!(Entry) entries; 37 38 this() 39 { 40 entries = new ArrayList!(Entry)(); 41 } 42 43 public this(string dbType) { 44 this(); 45 this.dbType = dbType; 46 } 47 48 public void add(string select) { 49 if (select is null || select.length == 0) { 50 return; 51 } 52 53 SQLSelectParser selectParser = SQLParserUtils.createSQLStatementParser(select, dbType) 54 .createSQLSelectParser(); 55 SQLSelectQueryBlock queryBlock = SQLParserUtils.createSelectQueryBlock(dbType); 56 selectParser.accept(Token.SELECT); 57 58 selectParser.parseSelectList(queryBlock); 59 60 selectParser.accept(Token.FROM); 61 selectParser.accept(Token.EOF); 62 63 string printSql = (cast(Object)(queryBlock)).toString(); 64 long printSqlHash = FnvHash.fnv1a_64_lower(printSql); 65 entries.add( 66 new Entry(select.substring(6) 67 , queryBlock 68 , printSql 69 , printSqlHash) 70 ); 71 72 if (entries.size() > 5) { 73 warning("SelectListCache is too large."); 74 } 75 } 76 77 public int getSize() { 78 return entries.size(); 79 } 80 81 public void clear() { 82 entries.clear(); 83 } 84 85 public bool match(Lexer lexer, SQLSelectQueryBlock queryBlock) { 86 if (lexer.token != Token.SELECT) { 87 return false; 88 } 89 90 int pos = lexer.pos; 91 string text = lexer.text; 92 93 for (int i = 0; i < entries.size(); i++) { 94 Entry entry = entries.get(i); 95 string block = entry.sql; 96 if (text.startsWith(block, pos)) { 97 //SQLSelectQueryBlock queryBlockCached = queryBlockCache.get(i); 98 // queryBlockCached.cloneSelectListTo(queryBlock); 99 queryBlock.setCachedSelectList(entry.printSql, entry.printSqlHash); 100 101 int len = pos + cast(int)(block.length); 102 lexer.reset(len, charAt(text, len), Token.FROM); 103 return true; 104 } 105 } 106 return false; 107 } 108 109 private static class Entry { 110 public string sql; 111 public SQLSelectQueryBlock queryBlock; 112 public string printSql; 113 public long printSqlHash; 114 115 public this(string sql, SQLSelectQueryBlock queryBlock, string printSql, long printSqlHash) { 116 this.sql = sql; 117 this.queryBlock = queryBlock; 118 this.printSql = printSql; 119 this.printSqlHash = printSqlHash; 120 } 121 } 122 }