From: <sh...@us...> - 2007-10-22 23:30:57
|
Revision: 10941 http://jedit.svn.sourceforge.net/jedit/?rev=10941&view=rev Author: shlomy Date: 2007-10-22 16:30:53 -0700 (Mon, 22 Oct 2007) Log Message: ----------- Initial implementation of cleaner DB design. Only partially usable. Modified Paths: -------------- plugins/CtagsInterface/trunk/design.txt plugins/CtagsInterface/trunk/src/ctags/CtagsInterfacePlugin.java plugins/CtagsInterface/trunk/src/ctags/Parser.java plugins/CtagsInterface/trunk/src/ctags/Runner.java plugins/CtagsInterface/trunk/src/ctags/TagList.java plugins/CtagsInterface/trunk/src/db/TagDB.java plugins/CtagsInterface/trunk/src/jedit/BufferWatcher.java plugins/CtagsInterface/trunk/src/options/DirsOptionPane.java plugins/CtagsInterface/trunk/src/options/ProjectsOptionPane.java Modified: plugins/CtagsInterface/trunk/design.txt =================================================================== --- plugins/CtagsInterface/trunk/design.txt 2007-10-22 21:33:18 UTC (rev 10940) +++ plugins/CtagsInterface/trunk/design.txt 2007-10-22 23:30:53 UTC (rev 10941) @@ -20,17 +20,17 @@ ORIGIN_ID: ID of origin (from ORIGINS table) Use cases: -- Checking if a saved/loaded buffer needs to be updated: ++ Checking if a saved/loaded buffer needs to be updated: Check if: SELECT TOP 1 FILE FROM FILES WHERE FILE={path} Returns non-empty result. -- Updating a saved/loaded buffer: ++ Updating a saved/loaded buffer: id = SELECT ID FROM FILES WHERE FILE={path} DELETE FROM TAGS WHERE ID={id} Run Ctags on buffer For each tag: INSERT INTO TAGS (FILE_ID, ...) VALUES ({id}, ...) -- Adding a temp tag file: ++ Adding a temp tag file: For each tag: id = SELECT ID FROM FILES WHERE FILE={path} if (id < 0) { Modified: plugins/CtagsInterface/trunk/src/ctags/CtagsInterfacePlugin.java =================================================================== --- plugins/CtagsInterface/trunk/src/ctags/CtagsInterfacePlugin.java 2007-10-22 21:33:18 UTC (rev 10940) +++ plugins/CtagsInterface/trunk/src/ctags/CtagsInterfacePlugin.java 2007-10-22 23:30:53 UTC (rev 10941) @@ -2,6 +2,8 @@ import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; +import java.sql.Types; +import java.util.HashSet; import java.util.Hashtable; import java.util.Vector; import java.util.regex.Matcher; @@ -23,6 +25,8 @@ import org.gjt.sp.jedit.io.VFSManager; import org.gjt.sp.jedit.textarea.JEditTextArea; +import ctags.Parser.TagHandler; + import projects.ProjectWatcher; import db.TagDB; @@ -38,7 +42,8 @@ private static BufferWatcher watcher; private static ProjectWatcher pvi; private static ActionSet actions; - + private static TagHandler tagHandler; + public void start() { db = new TagDB(); @@ -53,6 +58,11 @@ actions = new ActionSet(ACTION_SET); updateActions(); jEdit.addActionSet(actions); + tagHandler = new TagHandler() { + public void processTag(Hashtable<String, String> info) { + db.insertTag(info, -1); + } + }; } public void stop() @@ -61,6 +71,10 @@ db.shutdown(); } + static public TagDB getDB() { + return db; + } + static public void updateActions() { actions.removeAllActions(); QueryAction[] queries = ActionsOptionPane.loadActions(); @@ -92,20 +106,37 @@ } } static void printTags() { - dumpQuery("SELECT * FROM " + TagDB.TABLE_NAME); + dumpQuery("SELECT * FROM TAGS"); } static void printTagsContaining(View view) { String s = JOptionPane.showInputDialog("Substring:"); if (s == null || s.length() == 0) return; - dumpQuery("SELECT * FROM " + TagDB.TABLE_NAME + - " WHERE " + TagDB.NAME_COL + " LIKE '%" + s + "%'"); + dumpQuery("SELECT * FROM TAGS WHERE NAME LIKE '%" + s + "%'"); } - static void addTagFile(View view) { + // Adds a temporary tag file to the DB + // Existing tags from source files in the tag file are removed first. + static private void addTempTagFile(String tagFile) { + parser.parseTagFile(tagFile, new TagHandler() { + public void processTag(Hashtable<String, String> info) { + HashSet<String> fileSet = new HashSet<String>(); + String file = info.get(TagDB.TAGS_FILE_ID); + if (! fileSet.contains(file)) { + if (db.hasSourceFile(file)) + db.deleteTagsFromSourceFile(file); + fileSet.add(file); + } + db.insertTag(info, -1); + } + }); + } + + // Action: Prompt for a temporary tag file to add to the DB + static public void addTagFile(View view) { String tagFile = JOptionPane.showInputDialog("Tag file:"); if (tagFile == null || tagFile.length() == 0) return; - parser.parseTagFile(tagFile, db); + addTempTagFile(tagFile); } public static void jumpToQueryResults(final View view, String query) @@ -116,11 +147,16 @@ ResultSetMetaData meta; meta = rs.getMetaData(); String [] cols = new String[meta.getColumnCount()]; - for (int i = 0; i < cols.length; i++) + int [] types = new int[meta.getColumnCount()]; + for (int i = 0; i < cols.length; i++) { cols[i] = meta.getColumnName(i + 1); + types[i] = meta.getColumnType(i + 1); + } while (rs.next()) { Hashtable<String, String> values = new Hashtable<String, String>(); for (int i = 0; i < cols.length; i++) { + if (types[i] != Types.VARCHAR) + continue; String value = rs.getString(i + 1); if (value != null && value.length() > 0) values.put(cols[i], value); @@ -145,8 +181,8 @@ } tl.setTags(null); Hashtable<String, String> info = tags.get(index); - String file = info.get(TagDB.FILE_COL); - final int line = Integer.valueOf(info.get(TagDB.LINE_COL)); + String file = info.get(TagDB.TAGS_FILE_ID); + final int line = Integer.valueOf(info.get(TagDB.TAGS_LINE)); jumpTo(view, file, line); } @@ -154,16 +190,25 @@ { String tag = getDestinationTag(view); if (tag == null || tag.length() == 0) { - JOptionPane.showMessageDialog(view, "No tag selected nor identified at caret"); + JOptionPane.showMessageDialog( + view, "No tag selected nor identified at caret"); return; } //System.err.println("Selected tag: " + tag); - StringBuffer query = new StringBuffer( - "SELECT * FROM " + TagDB.TABLE_NAME + " WHERE " + - TagDB.NAME_COL + "=" + db.getValueString(tag)); - if (pvi != null && ProjectsOptionPane.getSearchActiveProjectOnly()) - query.append(" AND " + TagDB.PROJECT_COL + "='" + - pvi.getActiveProject(view) + "'"); + StringBuffer query = new StringBuffer("SELECT * FROM TAGS, FILES"); + boolean projectScope = (pvi != null && + ProjectsOptionPane.getSearchActiveProjectOnly()); + if (projectScope) + query.append(", MAP, ORIGINS"); + query.append(" WHERE TAGS.NAME= " + db.quote(tag) + + " AND TAGS.FILE_ID=FILES.ID"); + if (projectScope) { + String project = pvi.getActiveProject(view); + query.append(" AND ORIGINS.TYPE=PROJECT "); + query.append(" AND ORIGINS.ID=MAP.ORIGIN_ID "); + query.append(" AND FILES.ID=MAP.FILE_ID "); + query.append(" AND ORIGINS.NAME=" + db.quote(project)); + } jumpToQueryResults(view, query.toString()); } @@ -230,12 +275,16 @@ setStatusMessage("Tagging file: " + file); addWorkRequest(new Runnable() { public void run() { - db.deleteRowsWithValue(TagDB.FILE_COL, file); - runner.runOnFile(file); + db.deleteTagsFromSourceFile(file); + final int fileId = db.getSourceFileID(file); + runner.runOnFile(file, new TagHandler() { + public void processTag(Hashtable<String, String> info) { + db.insertTag(info, fileId); + } + }); } }, false); removeStatusMessage(); - } /* Source tree support */ @@ -244,8 +293,26 @@ setStatusMessage("Tagging source tree: " + tree); addWorkRequest(new Runnable() { public void run() { - db.deleteRowsWithValuePrefix(TagDB.FILE_COL, tree); - runner.runOnTree(tree); + int originId = db.queryInteger(TagDB.ORIGINS_ID, + "SELECT ID FROM ORIGINS WHERE TYPE='DIR' AND " + + "NAME=" + db.quote(tree), -1); + if (originId < 0) + return; + // Find file ids - required for cleanup + Vector<Integer> fileIds = db.queryIntegerList( + TagDB.MAP_FILE_ID, + "SELECT FILE_ID FROM MAP WHERE ORIGIN_ID=" + originId); + db.deleteRowsWithValue(TagDB.MAP_TABLE, TagDB.MAP_ORIGIN_ID, + Integer.valueOf(originId)); + db.deleteRowsWithValueList(TagDB.TAGS_TABLE, + TagDB.TAGS_FILE_ID, fileIds); + try { + db.query("DELETE FROM FILES WHERE NOT EXISTS (" + + "SELECT FILE_ID FROM MAP WHERE ID=FILE_ID)"); + } catch (SQLException e) { + e.printStackTrace(); + } + runner.runOnTree(tree, tagHandler); } }, false); removeStatusMessage(); @@ -258,7 +325,7 @@ } private static void removeProject(String project) { - db.deleteRowsWithValue(TagDB.PROJECT_COL, project); + //db.deleteRowsWithValue(TagDB.PROJECT_COL, project); } private static void removeProjectFiles(String project, Vector<String> files) @@ -266,7 +333,7 @@ Hashtable<String, String> values = new Hashtable<String, String>(); values.put(TagDB.PROJECT_COL, project); for (int i = 0; i < files.size(); i++) { - values.put(TagDB.FILE_COL, files.get(i)); + values.put(TagDB.TAGS_FILE_ID, files.get(i)); db.deleteRowsWithValues(values); } } @@ -274,7 +341,7 @@ Vector<String> files) { db.setProject(project); - runner.runOnFiles(files); + runner.runOnFiles(files, tagHandler); db.unsetProject(); } public static void tagProject(final String project) { Modified: plugins/CtagsInterface/trunk/src/ctags/Parser.java =================================================================== --- plugins/CtagsInterface/trunk/src/ctags/Parser.java 2007-10-22 21:33:18 UTC (rev 10940) +++ plugins/CtagsInterface/trunk/src/ctags/Parser.java 2007-10-22 23:30:53 UTC (rev 10941) @@ -13,7 +13,11 @@ String tagFileDir; - void parseTagFile(String tagFile, TagDB db) { + interface TagHandler { + void processTag(Hashtable<String, String> info); + } + + void parseTagFile(String tagFile, TagHandler handler) { if (tagFile == null || tagFile.length() == 0) return; tagFileDir = new File(tagFile).getAbsoluteFile().getParent(); @@ -30,7 +34,7 @@ Hashtable<String, String> info = parse(line); if (info == null) continue; - db.insertTag(info); + handler.processTag(info); } } catch (IOException e) { e.printStackTrace(); @@ -57,13 +61,13 @@ String fields[] = line.substring(0, idx).split("\t", 3); if (fields.length < 3) return null; - info.put(TagDB.NAME_COL, fields[0]); + info.put(TagDB.TAGS_NAME, fields[0]); String file = fields[1]; if (new File(file).isAbsolute()) - info.put(TagDB.FILE_COL, fields[1]); + info.put(TagDB.TAGS_FILE_ID, fields[1]); else - info.put(TagDB.FILE_COL, tagFileDir + "/" + fields[1]); - info.put(TagDB.PATTERN_COL, fields[2]); + info.put(TagDB.TAGS_FILE_ID, tagFileDir + "/" + fields[1]); + info.put(TagDB.TAGS_PATTERN, fields[2]); // Extensions fields = line.substring(idx + 3).split("\t"); for (int i = 0; i < fields.length; i++) Modified: plugins/CtagsInterface/trunk/src/ctags/Runner.java =================================================================== --- plugins/CtagsInterface/trunk/src/ctags/Runner.java 2007-10-22 21:33:18 UTC (rev 10940) +++ plugins/CtagsInterface/trunk/src/ctags/Runner.java 2007-10-22 23:30:53 UTC (rev 10941) @@ -5,35 +5,35 @@ import org.gjt.sp.jedit.jEdit; +import ctags.Parser.TagHandler; + import options.GeneralOptionPane; import db.TagDB; public class Runner { private static final String SPACES = "\\s+"; - private TagDB db; private Parser parser; public Runner(TagDB db) { - this.db = db; parser = null; } - public void runOnFile(String file) { + public void runOnFile(String file, TagHandler handler) { Vector<String> what = new Vector<String>(); what.add(file); - run(what); + run(what, handler); } - public void runOnTree(String tree) { + public void runOnTree(String tree, TagHandler handler) { Vector<String> what = new Vector<String>(); what.add("-R"); what.add(tree); - run(what); + run(what, handler); } - public void runOnFiles(Vector<String> files) { - run(files); + public void runOnFiles(Vector<String> files, TagHandler handler) { + run(files, handler); } - private void run(Vector<String> what) { + private void run(Vector<String> what, TagHandler handler) { String ctags = GeneralOptionPane.getCtags(); String cmd = GeneralOptionPane.getCmd(); String tagFile = getTempTagFilePath(); @@ -58,7 +58,7 @@ } if (parser == null) parser = new Parser(); - parser.parseTagFile(tagFile, db); + parser.parseTagFile(tagFile, handler); } private String getTempTagFilePath() { Modified: plugins/CtagsInterface/trunk/src/ctags/TagList.java =================================================================== --- plugins/CtagsInterface/trunk/src/ctags/TagList.java 2007-10-22 21:33:18 UTC (rev 10940) +++ plugins/CtagsInterface/trunk/src/ctags/TagList.java 2007-10-22 23:30:53 UTC (rev 10941) @@ -60,8 +60,8 @@ protected void jumpTo(int selectedIndex) { Hashtable<String, String> tag = (Hashtable<String, String>) tagModel.getElementAt(selectedIndex); - String file = tag.get(TagDB.FILE_COL); - String lineStr = tag.get(TagDB.LINE_COL); + String file = tag.get(TagDB.TAGS_FILE_ID); + String lineStr = tag.get(TagDB.TAGS_LINE); if (lineStr != null) { int line = Integer.valueOf(lineStr); CtagsInterfacePlugin.jumpTo(view, file, line); @@ -97,7 +97,7 @@ StringBuffer s = new StringBuffer("<html>"); s.append(index + 1); s.append(": <b>"); - s.append(tag.get(TagDB.NAME_COL)); + s.append(tag.get(TagDB.TAGS_NAME)); s.append("</b> "); String project = tag.get(TagDB.PROJECT_COL); if (project != null && project.length() > 0) { @@ -105,18 +105,18 @@ s.append(project); s.append("</i>) "); } - s.append(tag.get(TagDB.FILE_COL)); - s.append(tag.containsKey(TagDB.LINE_COL) ? ":" + - tag.get(TagDB.LINE_COL) : ""); + s.append(tag.get(TagDB.TAGS_FILE_ID)); + s.append(tag.containsKey(TagDB.TAGS_LINE) ? ":" + + tag.get(TagDB.TAGS_LINE) : ""); s.append("<br>Pattern: "); - s.append(tag.get(TagDB.PATTERN_COL)); + s.append(tag.get(TagDB.TAGS_PATTERN)); s.append("<br>"); TreeSet<String> keys = new TreeSet<String>(tag.keySet()); - keys.remove(TagDB.NAME_COL); - keys.remove(TagDB.FILE_COL); + keys.remove(TagDB.TAGS_NAME); + keys.remove(TagDB.TAGS_FILE_ID); keys.remove(TagDB.PROJECT_COL); - keys.remove(TagDB.LINE_COL); - keys.remove(TagDB.PATTERN_COL); + keys.remove(TagDB.TAGS_LINE); + keys.remove(TagDB.TAGS_PATTERN); Iterator<String> it = keys.iterator(); boolean first = true; while (it.hasNext()) { Modified: plugins/CtagsInterface/trunk/src/db/TagDB.java =================================================================== --- plugins/CtagsInterface/trunk/src/db/TagDB.java 2007-10-22 21:33:18 UTC (rev 10940) +++ plugins/CtagsInterface/trunk/src/db/TagDB.java 2007-10-22 23:30:53 UTC (rev 10941) @@ -11,6 +11,7 @@ import java.util.Hashtable; import java.util.Iterator; import java.util.Set; +import java.util.Vector; import java.util.Map.Entry; import org.gjt.sp.jedit.jEdit; @@ -18,14 +19,35 @@ public class TagDB { private Connection conn; private Set<String> columns; - private String project; - public static final String TABLE_NAME = "TAGS"; - public static final String NAME_COL = "K_NAME"; - public static final String FILE_COL = "K_FILE"; - public static final String PATTERN_COL = "K_PATTERN"; + // Column types + public static final String IDENTITY_TYPE = "IDENTITY"; + public static final String VARCHAR_TYPE = "VARCHAR"; + public static final String INTEGER_TYPE = "INTEGER"; + // Tags table + public static final String TAGS_TABLE = "TAGS"; + public static final String TAGS_NAME = "NAME"; + public static final String TAGS_FILE_ID = "FILE_ID"; + public static final String TAGS_PATTERN = "PATTERN"; + public static final String TAGS_ATTR_PREFIX = "A_"; + public static final String TAGS_LINE = "A_LINE"; + // Files table + public static final String FILES_TABLE = "FILES"; + public static final String FILES_ID = "ID"; + public static final String FILES_NAME = "FILE"; + // Origins table + public static final String ORIGINS_TABLE = "ORIGINS"; + public static final String ORIGINS_ID = "ID"; + public static final String ORIGINS_NAME = "NAME"; + public static final String ORIGINS_TYPE = "TYPE"; + // Files/Origin map table + public static final String MAP_TABLE = "MAP"; + public static final String MAP_FILE_ID = "FILE_ID"; + public static final String MAP_ORIGIN_ID = "ORIGIN_ID"; + // Origin types + public static final String PROJECT_ORIGIN = "Project"; + public static final String DIR_ORIGIN = "Dir"; + public static final String PROJECT_COL = "K_PROJECT"; - public static final String LINE_COL = "A_LINE"; - public static final String ATTR_PREFIX = "A_"; public TagDB() { removeStaleLock(); @@ -38,17 +60,149 @@ } createTables(); getColumns(); - project = ""; } + + // Check if a source file is in the DB + public boolean hasSourceFile(String file) { + return tableColumnContainsValue(FILES_TABLE, FILES_NAME, file); + } + // Returns the ID of a source file, or (-1) if source file not in DB + public int getSourceFileID(String file) { + return queryInteger(FILES_ID, "SELECT " + FILES_ID + " FROM " + FILES_TABLE + + " WHERE " + FILES_NAME + "=" + quote(file), -1); + } + + // Delete tags from source file + public void deleteTagsFromSourceFile(String file) { + int fileId = getSourceFileID(file); + if (fileId < 0) + return; + deleteRowsWithValue(TAGS_TABLE, TAGS_FILE_ID, Integer.valueOf(fileId)); + } + + /* + * Insert a tag into the DB with a given file ID. + * If file ID is negative, the ID is looked up in the FILES table. If the file + * is not in the table, it is inserted. + */ + public void insertTag(Hashtable<String, String> info, int fileId) { + if (fileId < 0) { + String file = info.get(TAGS_FILE_ID); + fileId = getSourceFileID(file); + if (fileId < 0) { // Need to insert the file + try { + update("INSERT INTO " + FILES_TABLE + " (" + FILES_NAME + ") VALUES (" + + quote(file) + ")"); + } catch (SQLException e) { + e.printStackTrace(); + } + fileId = getSourceFileID(file); + if (fileId < 0) + return; + } + } + info.remove(TAGS_FILE_ID); + // Find missing columns and build the inserted value string + StringBuffer valueStr = new StringBuffer(); + StringBuffer columnStr = new StringBuffer(); + Set<Entry<String,String>> entries = info.entrySet(); + Iterator<Entry<String, String>> it = entries.iterator(); + while (it.hasNext()) { + Entry<String, String> entry = it.next(); + String col = entry.getKey().toUpperCase(); + String val = entry.getValue(); + if (! columns.contains(col)) { + try { + update("ALTER TABLE " + TAGS_TABLE + " ADD " + col + " " + + VARCHAR_TYPE + ";"); + } catch (SQLException e) { + e.printStackTrace(); + } + columns.add(col); + } + if (columnStr.length() > 0) + columnStr.append(","); + columnStr.append(col); + if (valueStr.length() > 0) + valueStr.append(","); + valueStr.append(quote(val)); + } + // Insert the record + try { + update("INSERT INTO " + TAGS_TABLE + " (" + TAGS_FILE_ID + "," + + columnStr.toString() + ") VALUES (" + fileId + "," + valueStr.toString() + + ")"); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + /* + * Check if the table contains a row with the specified value in the specified column. + * Used for checking if a buffer is in the DB. + */ + private boolean tableColumnContainsValue(String table, String column, Object value) { + try { + ResultSet rs = query("SELECT TOP 1 " + column + " FROM " + table + " WHERE " + + column + "=" + quote(value)); + return rs.next(); + } catch (SQLException e) { + e.printStackTrace(); + } + return false; + } + + /* + * Runs a query and returns an integer value from the specified column of the first + * row in the query result, or defaultValue if the query result is empty. + */ + public int queryInteger(String column, String query, int defaultValue) { + try { + ResultSet rs = query(query); + if (! rs.next()) + return defaultValue; + return rs.getInt(column); + } catch (SQLException e) { + e.printStackTrace(); + } + return defaultValue; + } + + public Vector<String> getOrigins(String type) { + return queryStringList(ORIGINS_NAME, + "SELECT * FROM " + ORIGINS_TABLE + " WHERE " + + ORIGINS_TYPE + "=" + quote(type)); + } + public void updateOrigins(String type, Vector<String> values) { + // Remove obsolete origins + Vector<String> current = queryStringList(ORIGINS_NAME, + "SELECT * FROM " + ORIGINS_TABLE + " WHERE " + + ORIGINS_TYPE + "=" + quote(type)); + for (int i = 0; i < current.size(); i++) { + String name = current.get(i); + if (! values.contains(name)) + deleteOrigin(type, name); + } + // Add new origins + for (int i = 0; i < values.size(); i++) { + String name = values.get(i); + if (! current.contains(name)) + try { + insertOrigin(type, name); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + public void setProject(String project) { - this.project = project; } public void unsetProject() { - project = ""; } public synchronized void update(String expression) throws SQLException { + //System.err.println("update: " + expression); Statement st = conn.createStatement(); try { if (st.executeUpdate(expression) == -1) @@ -61,12 +215,36 @@ } public synchronized ResultSet query(String expression) throws SQLException { + //System.err.println("query: " + expression); Statement st = conn.createStatement(); ResultSet rs = st.executeQuery(expression); st.close(); return rs; } + public Vector<Integer> queryIntegerList(String column, String query) { + Vector<Integer> values = new Vector<Integer>(); + try { + ResultSet rs = query(query); + while (rs.next()) + values.add(Integer.valueOf(rs.getInt(column))); + } catch (SQLException e) { + e.printStackTrace(); + } + return values; + } + public Vector<String> queryStringList(String column, String query) { + Vector<String> values = new Vector<String>(); + try { + ResultSet rs = query(query); + while (rs.next()) + values.add(rs.getString(column)); + } catch (SQLException e) { + e.printStackTrace(); + } + return values; + } + public void shutdown() { try { @@ -78,62 +256,32 @@ } } - public void insertTag(Hashtable<String, String> info) { - // Find missing columns and build the inserted value string - info.put(PROJECT_COL, project); - StringBuffer valueStr = new StringBuffer(); - StringBuffer columnStr = new StringBuffer(); - Set<Entry<String,String>> entries = info.entrySet(); - Iterator<Entry<String, String>> it = entries.iterator(); - while (it.hasNext()) { - Entry<String, String> entry = it.next(); - String col = entry.getKey().toUpperCase(); - String val = entry.getValue(); - if (! columns.contains(col)) { - try { - update("ALTER TABLE " + TABLE_NAME + " ADD " + - col + " VARCHAR;"); - } catch (SQLException e) { - e.printStackTrace(); - } - columns.add(col); - } - if (columnStr.length() > 0) - columnStr.append(","); - columnStr.append(col); - if (valueStr.length() > 0) - valueStr.append(","); - valueStr.append(getValueString(val)); - } - // Insert the record - try { - update("INSERT INTO " + TABLE_NAME + " (" + - columnStr.toString() + ") VALUES (" + - valueStr.toString() + ")"); - } catch (SQLException e) { - e.printStackTrace(); - } + public String quote(Object value) { + if (value instanceof String) + return "'" + ((String)value).replaceAll("'", "''") + "'"; + return value.toString(); } - public String getValueString(String string) { - return "'" + string.replaceAll("'", "''") + "'"; - } - - public boolean containsValue(String column, String value) { + public void deleteRowsWithValue(String table, String column, Object value) { try { - ResultSet rs = query("SELECT TOP 1 " + column + " FROM " + - TABLE_NAME + " WHERE " + column + "=" + getValueString(value)); - return rs.next(); + query("DELETE FROM " + table + " WHERE " + column + "=" + quote(value)); } catch (SQLException e) { e.printStackTrace(); } - return false; } - public void deleteRowsWithValue(String column, String value) { + @SuppressWarnings("unchecked") + public void deleteRowsWithValueList(String table, String column, + Vector list) { + StringBuffer set = new StringBuffer(); + for (int i = 0; i < list.size(); i++) { + if (i > 0) + set.append(","); + set.append(quote(list.get(i))); + } try { - query("DELETE FROM " + TABLE_NAME + " WHERE " + column + - "=" + getValueString(value)); + query("DELETE FROM " + table + " WHERE " + column + " IN (" + + set.toString() + ")"); } catch (SQLException e) { e.printStackTrace(); } @@ -151,10 +299,10 @@ Entry<String, String> entry = it.next(); where.append(entry.getKey()); where.append("="); - where.append(getValueString(entry.getValue())); + where.append(quote(entry.getValue())); } try { - query("DELETE FROM " + TABLE_NAME + " WHERE " + where); + query("DELETE FROM TAGS WHERE " + where); } catch (SQLException e) { e.printStackTrace(); } @@ -162,40 +310,24 @@ public void deleteRowsWithValuePrefix(String column, String prefix) { try { - query("DELETE FROM " + TABLE_NAME + " WHERE " + column + - " LIKE " + getValueString(prefix + "%")); + query("DELETE FROM TAGS WHERE " + column + " LIKE " + + quote(prefix + "%")); } catch (SQLException e) { e.printStackTrace(); } } static public String attr2col(String attributeName) { - return ATTR_PREFIX + attributeName.toUpperCase(); + return TAGS_ATTR_PREFIX + attributeName.toUpperCase(); } static public String col2attr(String columnName) { - return columnName.substring(ATTR_PREFIX.length()).toLowerCase(); + return columnName.substring(TAGS_ATTR_PREFIX.length()).toLowerCase(); } - private void createTables() { - try { - update("CREATE CACHED TABLE " + TABLE_NAME + - "(" + NAME_COL + " VARCHAR, " + - FILE_COL + " VARCHAR, " + - PATTERN_COL + " VARCHAR, " + - PROJECT_COL + " VARCHAR)"); - update("CREATE INDEX tagName ON " + TABLE_NAME + "(" + NAME_COL + ")"); - update("CREATE INDEX fileName ON " + TABLE_NAME + "(" + FILE_COL + ")"); - update("CREATE INDEX projName ON " + TABLE_NAME + "(" + PROJECT_COL + ")"); - } catch (SQLException e) { - // Table already exists - } - } - private void getColumns() { columns = new HashSet<String>(); try { - ResultSet rs = query("SELECT * FROM " + TABLE_NAME + - " WHERE " + NAME_COL + "=''"); + ResultSet rs = query("SELECT * FROM TAGS WHERE NAME=''"); ResultSetMetaData meta = rs.getMetaData(); int cols = meta.getColumnCount(); for (int i = 0; i < cols; i++) @@ -215,4 +347,86 @@ if (lock.exists()) lock.delete(); } + + private void createIndex(String index, String table, String column) + throws SQLException { + update("CREATE INDEX " + index + " ON " + table + "(" + column + ")"); + } + + private void createTable(String table, String [] columns) + throws SQLException { + StringBuffer st = new StringBuffer("CREATE CACHED TABLE "); + st.append(table); + st.append("("); + for (int i = 0; i < columns.length; i += 2) { + if (i > 0) + st.append(", "); + st.append(columns[i]); + st.append(" "); + st.append(columns[i + 1]); + } + st.append(")"); + update(st.toString()); + } + + private void createTables() { + try { + // Create Tags table + createTable(TAGS_TABLE, new String [] { + TAGS_NAME, VARCHAR_TYPE, + TAGS_FILE_ID, INTEGER_TYPE, + TAGS_PATTERN, VARCHAR_TYPE + }); + createIndex("TAGS_NAME", TAGS_TABLE, TAGS_NAME); + createIndex("TAGS_FILE", TAGS_TABLE, TAGS_FILE_ID); + // Create Files table + createTable(FILES_TABLE, new String [] { + FILES_ID, IDENTITY_TYPE, + FILES_NAME, VARCHAR_TYPE + }); + createIndex("FILES_NAME", FILES_TABLE, FILES_NAME); + // Create Origins table + createTable(ORIGINS_TABLE, new String [] { + ORIGINS_ID, IDENTITY_TYPE, + ORIGINS_NAME, VARCHAR_TYPE, + ORIGINS_TYPE, VARCHAR_TYPE + }); + // Create Map table + createTable(MAP_TABLE, new String [] { + MAP_FILE_ID, INTEGER_TYPE, + MAP_ORIGIN_ID, INTEGER_TYPE + }); + createIndex("MAP_FILE_ID", MAP_TABLE, MAP_FILE_ID); + createIndex("MAP_ORIGIN_ID", MAP_TABLE, MAP_ORIGIN_ID); + } catch (SQLException e) { + // Table already exists + } + } + + private void insertOrigin(String type, String name) throws SQLException { + update("INSERT INTO " + ORIGINS_TABLE + " (" + + ORIGINS_TYPE + "," + ORIGINS_NAME + ") VALUES (" + + type + "," + name + ")"); + } + private void deleteOrigin(String type, String name) { + // TODO: Remove origin from origins table, remove all files + // originated in the removed origin only, and remove all tags + // from the removed files. + int originId = queryInteger(ORIGINS_ID, + "SELECT * FROM " + ORIGINS_TABLE + " WHERE " + + ORIGINS_TYPE + "=" + quote(type) + " AND " + + ORIGINS_NAME + "=" + quote(name), -1); + if (originId < 0) + return; + String fileIds = "SELECT FILE_ID FROM MAP WHERE ORIGIN_ID=" + + quote(originId); + String deleteTags = "DELETE FROM TAGS WHERE FILE_ID IN (" + + fileIds + ")"; + try { + query(deleteTags); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } Modified: plugins/CtagsInterface/trunk/src/jedit/BufferWatcher.java =================================================================== --- plugins/CtagsInterface/trunk/src/jedit/BufferWatcher.java 2007-10-22 21:33:18 UTC (rev 10940) +++ plugins/CtagsInterface/trunk/src/jedit/BufferWatcher.java 2007-10-22 23:30:53 UTC (rev 10941) @@ -49,7 +49,7 @@ System.err.println(file + " in monitored tree"); return true; } - if (db.containsValue(TagDB.FILE_COL, file)) { + if (db.hasSourceFile(file)) { System.err.println(file + " in db"); return true; } Modified: plugins/CtagsInterface/trunk/src/options/DirsOptionPane.java =================================================================== --- plugins/CtagsInterface/trunk/src/options/DirsOptionPane.java 2007-10-22 21:33:18 UTC (rev 10940) +++ plugins/CtagsInterface/trunk/src/options/DirsOptionPane.java 2007-10-22 23:30:53 UTC (rev 10941) @@ -21,10 +21,12 @@ import org.gjt.sp.jedit.gui.RolloverButton; import ctags.CtagsInterfacePlugin; +import db.TagDB; @SuppressWarnings("serial") public class DirsOptionPane extends AbstractOptionPane { + private static final String DIR_ORIGIN = TagDB.DIR_ORIGIN; static public final String OPTION = CtagsInterfacePlugin.OPTION; static public final String MESSAGE = CtagsInterfacePlugin.MESSAGE; static public final String DIRS = OPTION + "dirs."; @@ -84,17 +86,14 @@ } public void save() { + Vector<String> names = new Vector<String>(); int nDirs = dirsModel.size(); - jEdit.setIntegerProperty(DIRS + "size", nDirs); for (int i = 0; i < nDirs; i++) - jEdit.setProperty(DIRS + i, (String)dirsModel.getElementAt(i)); + names.add((String) dirsModel.getElementAt(i)); + CtagsInterfacePlugin.getDB().updateOrigins(DIR_ORIGIN, names); } static public Vector<String> getDirs() { - Vector<String> dirs = new Vector<String>(); - int nDirs = jEdit.getIntegerProperty(DIRS + "size"); - for (int i = 0; i < nDirs; i++) - dirs.add(jEdit.getProperty(DIRS + i)); - return dirs; + return CtagsInterfacePlugin.getDB().getOrigins(DIR_ORIGIN); } } Modified: plugins/CtagsInterface/trunk/src/options/ProjectsOptionPane.java =================================================================== --- plugins/CtagsInterface/trunk/src/options/ProjectsOptionPane.java 2007-10-22 21:33:18 UTC (rev 10940) +++ plugins/CtagsInterface/trunk/src/options/ProjectsOptionPane.java 2007-10-22 23:30:53 UTC (rev 10941) @@ -22,10 +22,12 @@ import projects.ProjectWatcher; import ctags.CtagsInterfacePlugin; +import db.TagDB; @SuppressWarnings("serial") public class ProjectsOptionPane extends AbstractOptionPane { + private static final String PROJECT_ORIGIN = TagDB.PROJECT_ORIGIN; static public final String OPTION = CtagsInterfacePlugin.OPTION; static public final String MESSAGE = CtagsInterfacePlugin.MESSAGE; static public final String PROJECTS = OPTION + "projects."; @@ -103,20 +105,17 @@ } public void save() { + Vector<String> names = new Vector<String>(); int nProjects = projectsModel.size(); - jEdit.setIntegerProperty(PROJECTS + "size", nProjects); for (int i = 0; i < nProjects; i++) - jEdit.setProperty(PROJECTS + i, (String)projectsModel.getElementAt(i)); + names.add((String) projectsModel.getElementAt(i)); + CtagsInterfacePlugin.getDB().updateOrigins(PROJECT_ORIGIN, names); jEdit.setBooleanProperty(AUTO_UPDATE, autoUpdate.isSelected()); jEdit.setBooleanProperty(ACTIVE_ONLY, activeOnly.isSelected()); } static public Vector<String> getProjects() { - Vector<String> projects = new Vector<String>(); - int nProjects = jEdit.getIntegerProperty(PROJECTS + "size"); - for (int i = 0; i < nProjects; i++) - projects.add(jEdit.getProperty(PROJECTS + i)); - return projects; + return CtagsInterfacePlugin.getDB().getOrigins(PROJECT_ORIGIN); } static public boolean getAutoUpdateProjects() { return jEdit.getBooleanProperty(AUTO_UPDATE); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |