diff options
author | Dawid Pakuła | 2014-12-11 10:59:13 +0000 |
---|---|---|
committer | Dawid Pakuła | 2015-01-06 10:46:00 +0000 |
commit | 0a0908c1dfd567178012e69b5f807d811fb80092 (patch) | |
tree | 2a8b4bd18dcdb5f8b5e13749a84583203a6a9c11 | |
parent | 2b5e32345cfafe01c16200e6fe189a051ba06cd6 (diff) | |
download | org.eclipse.dltk.core-0a0908c1dfd567178012e69b5f807d811fb80092.tar.gz org.eclipse.dltk.core-0a0908c1dfd567178012e69b5f807d811fb80092.tar.xz org.eclipse.dltk.core-0a0908c1dfd567178012e69b5f807d811fb80092.zip |
Bug 454867 - [H2] Optimize schema and search query
Signed-off-by: Dawid Pakuła <zulus@w3des.net>
Change-Id: Ifb26b6c87d4bb778e0fd9933eb9c79ef27fde97d
7 files changed, 57 insertions, 398 deletions
diff --git a/core/plugins/org.eclipse.dltk.core.index.sql.h2/resources/basic.sql b/core/plugins/org.eclipse.dltk.core.index.sql.h2/resources/basic.sql index 222bfa7ce..da61a7f9c 100644 --- a/core/plugins/org.eclipse.dltk.core.index.sql.h2/resources/basic.sql +++ b/core/plugins/org.eclipse.dltk.core.index.sql.h2/resources/basic.sql @@ -17,5 +17,7 @@ CREATE TABLE IF NOT EXISTS FILES( FOREIGN KEY(CONTAINER_ID) REFERENCES CONTAINERS(ID) ON UPDATE CASCADE ON DELETE CASCADE, ); -CREATE INDEX IDX_FILES_PATH_CONTAINER ON FILES(PATH, CONTAINER_ID); +CREATE INDEX IF NOT EXISTS IDX_FILES_PATH_CONTAINER ON FILES(PATH, CONTAINER_ID); +CREATE INDEX IF NOT EXISTS IDX_FILES_CONTAINER_ID ON FILES(CONTAINER_ID); +CREATE INDEX IF NOT EXISTS IDX_FILES_PATH ON FILES(PATH); diff --git a/core/plugins/org.eclipse.dltk.core.index.sql.h2/resources/element_decl.sql b/core/plugins/org.eclipse.dltk.core.index.sql.h2/resources/element_decl.sql index a72b41c25..92226169a 100644 --- a/core/plugins/org.eclipse.dltk.core.index.sql.h2/resources/element_decl.sql +++ b/core/plugins/org.eclipse.dltk.core.index.sql.h2/resources/element_decl.sql @@ -17,4 +17,12 @@ CREATE TABLE IF NOT EXISTS {0}( PARENT VARCHAR, FILE_ID INT NOT NULL, FOREIGN KEY(FILE_ID) REFERENCES FILES(ID) ON UPDATE CASCADE ON DELETE CASCADE, -);
\ No newline at end of file +); + +CREATE INDEX IF NOT EXISTS IDX_CC_NAME_{0} ON {0}(CC_NAME); +CREATE INDEX IF NOT EXISTS IDX_PARENT_{0} ON {0}(PARENT); +CREATE INDEX IF NOT EXISTS IDX_QUALIFIER_{0} ON {0}(QUALIFIER); +CREATE INDEX IF NOT EXISTS IDX_FILE_ID_{0} ON {0}(FILE_ID); +CREATE INDEX IF NOT EXISTS IDX_FLAGS_{0} ON {0}(FLAGS); +CREATE INDEX IF NOT EXISTS IDX_FULL_NAME_{0} ON {0}(NAME, QUALIFIER); +CREATE INDEX IF NOT EXISTS IDX_NAME_{0} ON {0}(NAME);
\ No newline at end of file diff --git a/core/plugins/org.eclipse.dltk.core.index.sql.h2/resources/element_ref.sql b/core/plugins/org.eclipse.dltk.core.index.sql.h2/resources/element_ref.sql index 2f754a609..06f52f7ba 100644 --- a/core/plugins/org.eclipse.dltk.core.index.sql.h2/resources/element_ref.sql +++ b/core/plugins/org.eclipse.dltk.core.index.sql.h2/resources/element_ref.sql @@ -11,4 +11,7 @@ CREATE TABLE IF NOT EXISTS {0}( QUALIFIER VARCHAR, FILE_ID INT NOT NULL, FOREIGN KEY(FILE_ID) REFERENCES FILES(ID) ON UPDATE CASCADE ON DELETE CASCADE, -);
\ No newline at end of file +); +CREATE INDEX IF NOT EXISTS IDX_QUALIFIER_{0} ON {0}(QUALIFIER); +CREATE INDEX IF NOT EXISTS IDX_FILE_ID_{0} ON {0}(FILE_ID); +CREATE INDEX IF NOT EXISTS IDX_NAME_{0} ON {0}(NAME);
\ No newline at end of file diff --git a/core/plugins/org.eclipse.dltk.core.index.sql.h2/src/org/eclipse/dltk/core/index/sql/h2/H2Index.java b/core/plugins/org.eclipse.dltk.core.index.sql.h2/src/org/eclipse/dltk/core/index/sql/h2/H2Index.java index 3811aa5b1..f0417ae4c 100644 --- a/core/plugins/org.eclipse.dltk.core.index.sql.h2/src/org/eclipse/dltk/core/index/sql/h2/H2Index.java +++ b/core/plugins/org.eclipse.dltk.core.index.sql.h2/src/org/eclipse/dltk/core/index/sql/h2/H2Index.java @@ -15,7 +15,6 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Plugin; import org.eclipse.core.runtime.Status; -import org.eclipse.dltk.internal.core.index.sql.h2.H2Cache; import org.osgi.framework.BundleContext; /** @@ -34,8 +33,6 @@ public class H2Index extends Plugin { public void start(BundleContext context) throws Exception { super.start(context); plugin = this; - - H2Cache.load(); } @Override @@ -55,9 +52,8 @@ public class H2Index extends Plugin { public static void error(String message) { plugin.getLog() - .log( - new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, - message, null)); + .log(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, message, + null)); } public static void error(String message, Throwable t) { diff --git a/core/plugins/org.eclipse.dltk.core.index.sql.h2/src/org/eclipse/dltk/internal/core/index/sql/h2/H2Cache.java b/core/plugins/org.eclipse.dltk.core.index.sql.h2/src/org/eclipse/dltk/internal/core/index/sql/h2/H2Cache.java index e9f612a43..d883499b7 100644 --- a/core/plugins/org.eclipse.dltk.core.index.sql.h2/src/org/eclipse/dltk/internal/core/index/sql/h2/H2Cache.java +++ b/core/plugins/org.eclipse.dltk.core.index.sql.h2/src/org/eclipse/dltk/internal/core/index/sql/h2/H2Cache.java @@ -11,31 +11,16 @@ *******************************************************************************/ package org.eclipse.dltk.internal.core.index.sql.h2; -import java.sql.Connection; -import java.sql.SQLException; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; -import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.jobs.ILock; import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.dltk.core.IModelElement; import org.eclipse.dltk.core.index.sql.Container; -import org.eclipse.dltk.core.index.sql.DbFactory; -import org.eclipse.dltk.core.index.sql.Element; import org.eclipse.dltk.core.index.sql.File; -import org.eclipse.dltk.core.index.sql.IElementDao; -import org.eclipse.dltk.core.index.sql.IElementHandler; -import org.eclipse.dltk.core.index.sql.h2.H2Index; -import org.eclipse.dltk.core.index2.search.ISearchEngine.MatchRule; /** * This is a cache layer between H2 database and model access @@ -50,12 +35,6 @@ public class H2Cache { private static final ILock fileLock = Job.getJobManager().newLock(); private static final Map<Integer, Map<Integer, File>> filesByContainer = new HashMap<Integer, Map<Integer, File>>(); - private static final ILock elementLock = Job.getJobManager().newLock(); - private static final Map<Integer, Map<Integer, List<Element>>> elementsMap = new HashMap<Integer, Map<Integer, List<Element>>>(); - - private static final ILock loadedLock = Job.getJobManager().newLock(); - private static boolean isLoaded; - public static void addContainer(Container container) { containerLock.acquire(); try { @@ -66,28 +45,6 @@ public class H2Cache { } } - public static void addElement(Element element) { - elementLock.acquire(); - try { - int elementType = element.getType(); - Map<Integer, List<Element>> elementsByFile = elementsMap - .get(elementType); - if (elementsByFile == null) { - elementsByFile = new HashMap<Integer, List<Element>>(); - elementsMap.put(elementType, elementsByFile); - } - int fileId = element.getFileId(); - List<Element> elementsSet = elementsByFile.get(fileId); - if (elementsSet == null) { - elementsSet = new LinkedList<Element>(); - elementsByFile.put(fileId, elementsSet); - } - elementsSet.add(element); - } finally { - elementLock.release(); - } - } - public static void addFile(File file) { fileLock.acquire(); try { @@ -125,20 +82,6 @@ public class H2Cache { } } - public static void deleteElementsByFileId(int id) { - elementLock.acquire(); - try { - Iterator<Map<Integer, List<Element>>> i = elementsMap.values() - .iterator(); - while (i.hasNext()) { - Map<Integer, List<Element>> elementsByFile = i.next(); - elementsByFile.remove(id); - } - } finally { - elementLock.release(); - } - } - public static void deleteFileByContainerIdAndPath(int containerId, String path) { fileLock.acquire(); @@ -160,7 +103,6 @@ public class H2Cache { while (i.hasNext()) { i.next().remove(id); } - deleteElementsByFileId(id); } finally { fileLock.release(); } @@ -169,13 +111,7 @@ public class H2Cache { public static void deleteFilesByContainerId(int id) { fileLock.acquire(); try { - Map<Integer, File> files = filesByContainer.remove(id); - if (files != null) { - Iterator<Integer> i = files.keySet().iterator(); - while (i.hasNext()) { - deleteElementsByFileId(i.next()); - } - } + filesByContainer.remove(id); } finally { fileLock.release(); } @@ -206,25 +142,6 @@ public class H2Cache { } } - public static Collection<Element> selectElementsByFileId(int id) { - elementLock.acquire(); - try { - List<Element> elements = new LinkedList<Element>(); - Iterator<Map<Integer, List<Element>>> i = elementsMap.values() - .iterator(); - while (i.hasNext()) { - Map<Integer, List<Element>> elementsByFile = i.next(); - List<Element> l = elementsByFile.get(id); - if (l != null) { - elements.addAll(l); - } - } - return elements; - } finally { - elementLock.release(); - } - } - public static File selectFileByContainerIdAndPath(int containerId, String path) { fileLock.acquire(); @@ -274,257 +191,4 @@ public class H2Cache { fileLock.release(); } } - - public static Collection<Element> searchElements(String pattern, - MatchRule matchRule, int elementType, int trueFlags, - int falseFlags, String qualifier, String parent, int[] filesId, - int containersId[], String natureId, int limit) { - - Set<Integer> filesIds = new HashSet<Integer>(); - if (filesId != null) { - for (int fileId : filesId) { - filesIds.add(fileId); - } - } else if (containersId != null) { - containerLock.acquire(); - try { - for (int containerId : containersId) { - fileLock.acquire(); - try { - Map<Integer, File> files = filesByContainer - .get(containerId); - if (files != null) { - filesIds.addAll(files.keySet()); - } - } finally { - fileLock.release(); - } - } - } finally { - containerLock.release(); - } - } - - elementLock.acquire(); - try { - Set<String> patternSet = null; - Pattern posixPattern = null; - - // Pre-cache pattern's lower and upper case variants: - String patternLC = null; - String patternUC = null; - if (pattern != null) { - patternLC = pattern.toLowerCase(); - patternUC = pattern.toUpperCase(); - } - - if (matchRule == MatchRule.SET) { - patternSet = new HashSet<String>(); - String[] parts = pattern.split(","); - for (String part : parts) { - if (part.length() > 0) { - patternSet.add(part.toLowerCase()); - } - } - } else if (matchRule == MatchRule.PATTERN) { - posixPattern = createPosixPattern(pattern); - } - - List<Element> result = new LinkedList<Element>(); - Map<Integer, List<Element>> elementsByFile = elementsMap - .get(elementType); - if (elementsByFile != null) { - - if (filesIds.size() == 0) { - Iterator<List<Element>> i = elementsByFile.values() - .iterator(); - while (i.hasNext()) { - searchInElements(i.next(), result, pattern, matchRule, - trueFlags, falseFlags, qualifier, parent, - patternSet, posixPattern, patternLC, patternUC, - limit); - } - } else { - for (Integer fileId : filesIds) { - searchInElements(elementsByFile.get(fileId), result, - pattern, matchRule, trueFlags, falseFlags, - qualifier, parent, patternSet, posixPattern, - patternLC, patternUC, limit); - } - } - } - return result; - - } finally { - elementLock.release(); - } - } - - private static void searchInElements(List<Element> elements, - List<Element> result, String pattern, MatchRule matchRule, - int trueFlags, int falseFlags, String qualifier, String parent, - Set<String> patternSet, Pattern posixPattern, String patternLC, - String patternUC, int limit) { - - if (elements != null) { - Iterator<Element> i = elements.iterator(); - while (i.hasNext()) { - Element element = i.next(); - if (elementMatches(element, pattern, matchRule, trueFlags, - falseFlags, qualifier, parent, patternSet, - posixPattern, patternLC, patternUC)) { - - result.add(element); - if (--limit == 0) { - break; - } - } - } - } - } - - private static boolean elementMatches(Element element, String pattern, - MatchRule matchRule, int trueFlags, int falseFlags, - String qualifier, String parent, Set<String> patternSet, - Pattern posixPattern, String patternLC, String patternUC) { - - if ((trueFlags == 0 || (element.getFlags() & trueFlags) != 0) - && (falseFlags == 0 || (element.getFlags() & falseFlags) == 0)) { - - if (qualifier == null || qualifier.length() == 0 - || qualifier.equals(element.getQualifier())) { - - if (parent == null || parent.length() == 0 - || parent.equals(element.getParent())) { - - String elementName = element.getName(); - if (pattern == null - || pattern.length() == 0 - || (matchRule == MatchRule.EXACT && pattern - .equalsIgnoreCase(elementName)) - || (matchRule == MatchRule.PREFIX && startsWithIgnoreCase( - elementName, patternLC)) - || (matchRule == MatchRule.CAMEL_CASE - && element.getCamelCaseName() != null && element - .getCamelCaseName().startsWith(patternUC)) - || (matchRule == MatchRule.SET && patternSet - .contains(elementName.toLowerCase())) - || (matchRule == MatchRule.PATTERN && posixPattern - .matcher(elementName).matches())) { - return true; - } - } - } - } - return false; - } - - private static Pattern createPosixPattern(String pattern) { - StringBuilder buf = new StringBuilder(); - boolean inQuoted = false; - for (int i = 0; i < pattern.length(); ++i) { - char ch = pattern.charAt(i); - if (ch == '*') { - if (inQuoted) { - buf.append("\\E"); - inQuoted = false; - } - buf.append(".*"); - } else if (ch == '?') { - if (inQuoted) { - buf.append("\\E"); - inQuoted = false; - } - buf.append(".?"); - } else { - if (!inQuoted) { - buf.append("\\Q"); - inQuoted = true; - } - buf.append(ch); - } - } - return Pattern.compile(buf.toString(), Pattern.CASE_INSENSITIVE); - } - - private static boolean startsWithIgnoreCase(String str, String prefix) { - return startsWith(str, prefix, true); - } - - private static boolean startsWith(String str, String prefix, - boolean ignoreCase) { - if (str == null || prefix == null) { - return (str == null && prefix == null); - } - if (prefix.length() > str.length()) { - return false; - } - return str.regionMatches(ignoreCase, 0, prefix, 0, prefix.length()); - } - - public static boolean isLoaded() { - loadedLock.acquire(); - try { - return isLoaded; - } finally { - loadedLock.release(); - } - } - - public static void load() { - loadedLock.acquire(); - try { - if (!isLoaded) { - try { - DbFactory dbFactory = DbFactory.getInstance(); - Connection connection = dbFactory.createConnection(); - try { - IElementDao elementDao = dbFactory.getElementDao(); - elementDao.search(connection, null, MatchRule.PREFIX, - IModelElement.FIELD, 0, 0, null, null, null, - null, "org.eclipse.php.core.PHPNature", 0, - false, new IElementHandler() { - public void handle(Element element) { - } - }, new NullProgressMonitor()); - - elementDao.search(connection, null, MatchRule.PREFIX, - IModelElement.TYPE, 0, 0, null, null, null, - null, "org.eclipse.php.core.PHPNature", 0, - false, new IElementHandler() { - public void handle(Element element) { - } - }, new NullProgressMonitor()); - - elementDao.search(connection, null, MatchRule.PREFIX, - IModelElement.METHOD, 0, 0, null, null, null, - null, "org.eclipse.php.core.PHPNature", 0, - false, new IElementHandler() { - public void handle(Element element) { - } - }, new NullProgressMonitor()); - - elementDao.search(connection, null, MatchRule.PREFIX, - IModelElement.IMPORT_DECLARATION, 0, 0, null, - null, null, null, - "org.eclipse.php.core.PHPNature", 0, false, - new IElementHandler() { - public void handle(Element element) { - } - }, new NullProgressMonitor()); - } finally { - connection.close(); - } - } catch (SQLException e) { - if (H2Index.DEBUG) { - e.printStackTrace(); - } - } finally { - isLoaded = true; - } - } - } finally { - loadedLock.release(); - } - } } diff --git a/core/plugins/org.eclipse.dltk.core.index.sql.h2/src/org/eclipse/dltk/internal/core/index/sql/h2/H2ElementDao.java b/core/plugins/org.eclipse.dltk.core.index.sql.h2/src/org/eclipse/dltk/internal/core/index/sql/h2/H2ElementDao.java index ed4153c5a..3009d8b2d 100644 --- a/core/plugins/org.eclipse.dltk.core.index.sql.h2/src/org/eclipse/dltk/internal/core/index/sql/h2/H2ElementDao.java +++ b/core/plugins/org.eclipse.dltk.core.index.sql.h2/src/org/eclipse/dltk/internal/core/index/sql/h2/H2ElementDao.java @@ -16,7 +16,6 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -79,21 +78,16 @@ public class H2ElementDao implements IElementDao { throws SQLException { int param = 0; - if (!isReference) { statement.setInt(++param, flags); } - statement.setInt(++param, offset); statement.setInt(++param, length); - if (!isReference) { statement.setInt(++param, nameOffset); statement.setInt(++param, nameLength); } - statement.setString(++param, name); - String camelCaseName = null; if (!isReference) { StringBuilder camelCaseNameBuf = new StringBuilder(); @@ -110,25 +104,16 @@ public class H2ElementDao implements IElementDao { .toString() : null; statement.setString(++param, camelCaseName); } - statement.setString(++param, metadata); if (!isReference) { statement.setString(++param, doc); } statement.setString(++param, qualifier); - if (!isReference) { statement.setString(++param, parent); } - statement.setInt(++param, fileId); statement.addBatch(); - - if (!isReference) { - H2Cache.addElement(new Element(type, flags, offset, length, - nameOffset, nameLength, name, camelCaseName, metadata, doc, - qualifier, parent, fileId, isReference)); - } } public void insert(Connection connection, int type, int flags, int offset, @@ -153,7 +138,6 @@ public class H2ElementDao implements IElementDao { D_INSERT_QUERY_CACHE.put(tableName, query); } } - synchronized (batchStatements) { PreparedStatement statement = batchStatements.get(query); if (statement == null) { @@ -192,26 +176,28 @@ public class H2ElementDao implements IElementDao { long timeStamp = System.currentTimeMillis(); int count = 0; - if (!isReference && H2Cache.isLoaded()) { - Collection<Element> elements = H2Cache.searchElements(pattern, - matchRule, elementType, trueFlags, falseFlags, qualifier, - parent, filesId, containersId, natureId, limit); - if (elements != null && elements.size() > 0) { - for (Element element : elements) { - handler.handle(element); - } - } - return; - } - String tableName = getTableName(connection, elementType, natureId, isReference); - final StringBuilder query = new StringBuilder("SELECT * FROM ") + final StringBuilder begin = new StringBuilder("SELECT T.* FROM ") .append(tableName); - final List<String> parameters = new ArrayList<String>(); - // Dummy pattern - query.append(" WHERE 1=1"); + + StringBuilder query = new StringBuilder(); + final List<Object> parameters = new ArrayList<Object>(); + + if (filesId == null && containersId != null && containersId.length > 0) { + begin.append(" AS T INNER JOIN FILES AS F ON (T.FILE_ID = F.ID AND F.CONTAINER_ID IN("); + for (int i = 0; i < containersId.length; ++i) { + if (i > 0) { + begin.append(","); + } + begin.append("?"); + parameters.add(containersId[i]); + } + begin.append(") )"); + } else { + begin.append(" AS T"); + } // Name patterns if (pattern != null && pattern.length() > 0) { @@ -257,12 +243,12 @@ public class H2ElementDao implements IElementDao { // Flags if (trueFlags != 0) { - query.append(" AND BITAND(FLAGS,").append(trueFlags) - .append(") <> 0"); + query.append(" AND BITAND(FLAGS, ?) <> 0"); + parameters.add(trueFlags); } if (falseFlags != 0) { - query.append(" AND BITAND(FLAGS,").append(falseFlags) - .append(") = 0"); + query.append(" AND BITAND(FLAGS,?) = 0"); + parameters.add(falseFlags); } // Qualifier @@ -283,19 +269,17 @@ public class H2ElementDao implements IElementDao { if (i > 0) { query.append(","); } - query.append(filesId[i]); + query.append("?"); + parameters.add(filesId[i]); } query.append(")"); + } - } else if (containersId != null) { - query.append(" AND FILE_ID IN(SELECT ID FROM FILES WHERE CONTAINER_ID IN("); - for (int i = 0; i < containersId.length; ++i) { - if (i > 0) { - query.append(","); - } - query.append(containersId[i]); - } - query.append("))"); + if (query.length() > 0) { + begin.append(" WHERE ").append(query.substring(4)); + query = begin; + } else { + query = begin; } // Records limit @@ -312,7 +296,12 @@ public class H2ElementDao implements IElementDao { .toString()); try { for (int i = 0; i < parameters.size(); ++i) { - statement.setString(i + 1, parameters.get(i)); + final Object param = parameters.get(i); + if (param instanceof Integer) { + statement.setInt(i + 1, (Integer) param); + } else { + statement.setString(i + 1, (String) param); + } } final ResultSet result = statement.executeQuery(); @@ -324,7 +313,7 @@ public class H2ElementDao implements IElementDao { } int columnIndex = 0; - int id = result.getInt(++columnIndex); + result.getInt(++columnIndex); int f = 0; if (!isReference) { @@ -364,9 +353,6 @@ public class H2ElementDao implements IElementDao { length, nameOffset, nameLength, modelManager.intern(name), camelCaseName, metadata, doc, qualifier, parent, fileId, isReference); - if (!isReference) { - H2Cache.addElement(element); - } handler.handle(element); } diff --git a/core/plugins/org.eclipse.dltk.core.index.sql.h2/src/org/eclipse/dltk/internal/core/index/sql/h2/Schema.java b/core/plugins/org.eclipse.dltk.core.index.sql.h2/src/org/eclipse/dltk/internal/core/index/sql/h2/Schema.java index a00846c6f..c6d9487b0 100644 --- a/core/plugins/org.eclipse.dltk.core.index.sql.h2/src/org/eclipse/dltk/internal/core/index/sql/h2/Schema.java +++ b/core/plugins/org.eclipse.dltk.core.index.sql.h2/src/org/eclipse/dltk/internal/core/index/sql/h2/Schema.java @@ -39,7 +39,7 @@ import org.osgi.service.prefs.BackingStoreException; */ public class Schema { - public static final String VERSION = "0.7.1"; //$NON-NLS-1$ + public static final String VERSION = "0.8.0"; //$NON-NLS-1$ /** Contains already created tables names */ private static final Set<String> TABLES_CACHE = new HashSet<String>(); |