Search in sources :

Example 1 with NameCompleter

use of henplus.view.util.NameCompleter in project henplus by neurolabs.

the class DumpCommand method execute.

/**
     * execute the command given.
     */
@Override
public int execute(final SQLSession session, final String cmd, final String param) {
    // final String FILE_ENCODING = System.getProperty("file.encoding");
    final StringTokenizer st = new StringTokenizer(param);
    final int argc = st.countTokens();
    if ("dump-select".equals(cmd)) {
        if (session == null) {
            Logger.error("not connected.");
            return EXEC_FAILED;
        }
        if (argc < 4) {
            return SYNTAX_ERROR;
        }
        final String fileName = st.nextToken();
        final String tabName = st.nextToken();
        final String select = st.nextToken();
        if (!select.toUpperCase().equals("SELECT")) {
            Logger.error("'select' expected.");
            return SYNTAX_ERROR;
        }
        final StringBuilder statement = new StringBuilder("select");
        while (st.hasMoreElements()) {
            statement.append(" ").append(st.nextToken());
        }
        PrintStream out = null;
        beginInterruptableSection();
        try {
            out = openOutputStream(fileName, FILE_ENCODING);
            final int result = dumpSelect(session, tabName, statement.toString(), out, FILE_ENCODING);
            return result;
        } catch (final Exception e) {
            Logger.error("failed: ", e);
            return EXEC_FAILED;
        } finally {
            if (out != null) {
                out.close();
            }
            endInterruptableSection();
        }
    } else if ("dump-conditional".equals(cmd)) {
        if (session == null) {
            Logger.error("not connected.");
            return EXEC_FAILED;
        }
        if (argc < 2) {
            return SYNTAX_ERROR;
        }
        final String fileName = (String) st.nextElement();
        final String tabName = (String) st.nextElement();
        String whereClause = null;
        if (argc >= 3) {
            // till EOL
            whereClause = st.nextToken("\n");
            whereClause = whereClause.trim();
            if (whereClause.toUpperCase().startsWith("WHERE")) {
                whereClause = whereClause.substring(5);
                whereClause = whereClause.trim();
            }
        }
        PrintStream out = null;
        beginInterruptableSection();
        try {
            out = openOutputStream(fileName, FILE_ENCODING);
            final int result = dumpTable(session, tabName, whereClause, out, FILE_ENCODING);
            return result;
        } catch (final Exception e) {
            Logger.error("failed: ", e);
            e.printStackTrace();
            return EXEC_FAILED;
        } finally {
            if (out != null) {
                out.close();
            }
            endInterruptableSection();
        }
    } else if ("dump-out".equals(cmd)) {
        if (session == null) {
            Logger.error("not connected.");
            return EXEC_FAILED;
        }
        if (argc < 2) {
            return SYNTAX_ERROR;
        }
        final String fileName = (String) st.nextElement();
        PrintStream out = null;
        final String tabName = null;
        beginInterruptableSection();
        try {
            final long startTime = System.currentTimeMillis();
            // which tables got already
            final Set<String> alreadyDumped = new HashSet<String>();
            // dumped?
            out = openOutputStream(fileName, FILE_ENCODING);
            final Set<String> tableSet = new LinkedHashSet<String>();
            /*
                 * right now, we do only a sort, if there is any '*' found in
                 * tables. Probably we might want to make this an option to
                 * dump-in
                 */
            boolean needsSort = false;
            int dumpResult = SUCCESS;
            /* 1) collect tables */
            while (st.hasMoreElements()) {
                final String nextToken = st.nextToken();
                if ("*".equals(nextToken) || nextToken.indexOf('*') > -1) {
                    needsSort = true;
                    Iterator<String> iter = null;
                    if ("*".equals(nextToken)) {
                        iter = _tableCompleter.getTableNamesIteratorForSession(session);
                    } else if (nextToken.indexOf('*') > -1) {
                        final String tablePrefix = nextToken.substring(0, nextToken.length() - 1);
                        final SortedSet<String> tableNames = _tableCompleter.getTableNamesForSession(session);
                        final NameCompleter compl = new NameCompleter(tableNames);
                        iter = compl.getAlternatives(tablePrefix);
                    }
                    while (iter.hasNext()) {
                        tableSet.add(iter.next());
                    }
                } else {
                    tableSet.add(nextToken);
                }
            }
            /* 2) resolve dependencies */
            ResolverResult resolverResult = null;
            List<String> tableSequence;
            if (needsSort) {
                tableSequence = new ArrayList<String>();
                Logger.info("Retrieving and sorting tables. This may take a while, please be patient.");
                // get sorted tables
                final SQLMetaData meta = new SQLMetaDataBuilder().getMetaData(session, tableSet.iterator());
                final DependencyResolver dr = new DependencyResolver(meta.getTables());
                resolverResult = dr.sortTables();
                final Collection<Table> tabs = resolverResult.getTables();
                final Iterator<Table> it = tabs.iterator();
                while (it.hasNext()) {
                    tableSequence.add(it.next().getName());
                }
            } else {
                tableSequence = new ArrayList<String>(tableSet);
            }
            /* 3) dump out */
            if (tableSequence.size() > 1) {
                Logger.info("%s tables to dump.", tableSequence.size());
            }
            final Iterator<String> it = tableSequence.iterator();
            while (_running && it.hasNext()) {
                final String table = it.next();
                if (!alreadyDumped.contains(table)) {
                    final int result = dumpTable(session, table, null, out, FILE_ENCODING, alreadyDumped);
                    if (result != SUCCESS) {
                        dumpResult = result;
                    }
                }
            }
            if (tableSequence.size() > 1) {
                final long duration = System.currentTimeMillis() - startTime;
                // TODO: move to Logger, timerenderer returns strings.
                HenPlus.msg().print("Dumping " + tableSequence.size() + " tables took ");
                TimeRenderer.printTime(duration, HenPlus.msg());
                HenPlus.msg().println();
            }
            /* 4) warn about cycles */
            if (resolverResult != null && resolverResult.getCyclicDependencies() != null && resolverResult.getCyclicDependencies().size() > 0) {
                HenPlus.msg().println("-----------\n" + "NOTE: There have been cyclic dependencies between several tables detected.\n" + "These may cause trouble when dumping in the currently dumped data.");
                // TODO: soll count nicht vielleicht hochgezählt werden
                final int count = 0;
                final StringBuilder sb = new StringBuilder();
                for (Collection<Table> tables : resolverResult.getCyclicDependencies()) {
                    sb.append("Cycle ").append(count).append(": ");
                    for (Table table : tables) {
                        sb.append(table.getName()).append(" -> ");
                    }
                    sb.delete(sb.length() - 4, sb.length()).append('\n');
                }
                HenPlus.msg().print(sb.toString());
            /* todo: print out, what constraint to disable */
            }
            return dumpResult;
        } catch (final Exception e) {
            HenPlus.msg().println("dump table '" + tabName + "' failed: " + e.getMessage());
            e.printStackTrace();
            return EXEC_FAILED;
        } finally {
            if (out != null) {
                out.close();
            }
            endInterruptableSection();
        }
    } else if ("dump-in".equals(cmd)) {
        if (session == null) {
            HenPlus.msg().println("not connected. Only verify-dump possible.");
            return EXEC_FAILED;
        }
        if (argc < 1 || argc > 2) {
            return SYNTAX_ERROR;
        }
        final String fileName = (String) st.nextElement();
        int commitPoint = -1;
        if (argc == 2) {
            try {
                final String val = (String) st.nextElement();
                commitPoint = Integer.valueOf(val).intValue();
            } catch (final NumberFormatException e) {
                HenPlus.msg().println("commit point number expected: " + e);
                return SYNTAX_ERROR;
            }
        }
        return retryReadDump(fileName, session, commitPoint);
    } else if ("verify-dump".equals(cmd)) {
        if (argc != 1) {
            return SYNTAX_ERROR;
        }
        final String fileName = (String) st.nextElement();
        return retryReadDump(fileName, null, -1);
    }
    return SYNTAX_ERROR;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) PrintStream(java.io.PrintStream) Table(henplus.sqlmodel.Table) NameCompleter(henplus.view.util.NameCompleter) ResolverResult(henplus.util.DependencyResolver.ResolverResult) SortedSet(java.util.SortedSet) SQLException(java.sql.SQLException) IOException(java.io.IOException) DependencyResolver(henplus.util.DependencyResolver) SQLMetaData(henplus.SQLMetaData) StringTokenizer(java.util.StringTokenizer) SQLMetaDataBuilder(henplus.SQLMetaDataBuilder) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 2 with NameCompleter

use of henplus.view.util.NameCompleter in project henplus by neurolabs.

the class DumpCommand method complete.

/**
     * complete the table name.
     */
@Override
public Iterator<String> complete(final CommandDispatcher disp, final String partialCommand, String lastWord) {
    final StringTokenizer st = new StringTokenizer(partialCommand);
    final String cmd = (String) st.nextElement();
    int argc = st.countTokens();
    if (lastWord.length() > 0) {
        argc--;
    }
    if ("dump-conditional".equals(cmd)) {
        if (argc == 0) {
            return new FileCompletionIterator(partialCommand, lastWord);
        } else if (argc == 1) {
            if (lastWord.startsWith("\"")) {
                lastWord = lastWord.substring(1);
            }
            return _tableCompleter.completeTableName(HenPlus.getInstance().getCurrentSession(), lastWord);
        } else if (argc > 1) {
            // discard filename.
            st.nextElement();
            final String table = (String) st.nextElement();
            final Collection<String> columns = _tableCompleter.columnsFor(table);
            final NameCompleter compl = new NameCompleter(columns);
            return compl.getAlternatives(lastWord);
        }
    } else if ("dump-out".equals(cmd)) {
        // this is true for dump-out und verify-dump
        if (argc == 0) {
            return new FileCompletionIterator(partialCommand, lastWord);
        }
        if (argc > 0) {
            if (lastWord.startsWith("\"")) {
                lastWord = lastWord.substring(1);
            }
            final HashSet<String> alreadyGiven = new HashSet<String>();
            /*
                 * do not complete the tables we already gave on the
                 * commandline.
                 */
            while (st.hasMoreElements()) {
                alreadyGiven.add(st.nextToken());
            }
            final Iterator<String> it = _tableCompleter.completeTableName(HenPlus.getInstance().getCurrentSession(), lastWord);
            return new Iterator<String>() {

                String table = null;

                @Override
                public boolean hasNext() {
                    while (it.hasNext()) {
                        table = (String) it.next();
                        if (alreadyGiven.contains(table)) {
                            continue;
                        }
                        return true;
                    }
                    return false;
                }

                @Override
                public String next() {
                    return table;
                }

                @Override
                public void remove() {
                    throw new UnsupportedOperationException("no!");
                }
            };
        }
    } else {
        if (argc == 0) {
            return new FileCompletionIterator(partialCommand, lastWord);
        }
    }
    return null;
}
Also used : StringTokenizer(java.util.StringTokenizer) NameCompleter(henplus.view.util.NameCompleter) Iterator(java.util.Iterator) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 3 with NameCompleter

use of henplus.view.util.NameCompleter in project henplus by neurolabs.

the class SQLCommand method complete.

// very simple completer: try to determine wether we can complete a
// table name. that is: if some keyword has been found before, switch to
// table-completer-mode :-)
@Override
public Iterator<String> complete(final CommandDispatcher disp, final String partialCommand, final String lastWord) {
    final String canonCmd = partialCommand.toUpperCase();
    /*
         * look for keywords that expect table names
         */
    int tableMatch = -1;
    for (int i = 0; i < TABLE_COMPLETER_KEYWORD.length; ++i) {
        final int match = canonCmd.indexOf(TABLE_COMPLETER_KEYWORD[i]);
        if (match >= 0) {
            tableMatch = match + TABLE_COMPLETER_KEYWORD[i].length();
            break;
        }
    }
    if (tableMatch < 0) {
        /*
             * ok, try to complete all columns from all tables since we don't
             * know yet what table the column will be from.
             */
        return _tableCompleter.completeAllColumns(lastWord);
    }
    // where the table declaration ends.
    int endTabMatch = -1;
    if (canonCmd.indexOf("UPDATE") >= 0) {
        endTabMatch = canonCmd.indexOf("SET");
    } else if (canonCmd.indexOf("INSERT") >= 0) {
        endTabMatch = canonCmd.indexOf("(");
    } else if (canonCmd.indexOf("WHERE") >= 0) {
        endTabMatch = canonCmd.indexOf("WHERE");
    } else if (canonCmd.indexOf("ORDER BY") >= 0) {
        endTabMatch = canonCmd.indexOf("ORDER BY");
    } else if (canonCmd.indexOf("GROUP BY") >= 0) {
        endTabMatch = canonCmd.indexOf("GROUP BY");
    }
    if (endTabMatch < 0) {
        endTabMatch = canonCmd.indexOf(";");
    }
    if (endTabMatch > tableMatch) {
        /*
             * column completion for the tables mentioned between in the table
             * area. This acknowledges as well aliases and prepends the names
             * with these aliases, if necessary.
             */
        final String tables = partialCommand.substring(tableMatch, endTabMatch);
        final HashMap<String, Set<String>> tmp = new HashMap<String, Set<String>>();
        for (Entry<String, String> entry : tableDeclParser(tables).entrySet()) {
            final String alias = entry.getKey();
            String tabName = entry.getValue();
            tabName = _tableCompleter.correctTableName(tabName);
            if (tabName == null) {
                continue;
            }
            final Collection<String> columns = _tableCompleter.columnsFor(tabName);
            final Iterator<String> cit = columns.iterator();
            while (cit.hasNext()) {
                final String col = cit.next();
                Set<String> aliases = tmp.get(col);
                if (aliases == null) {
                    aliases = new HashSet<String>();
                }
                aliases.add(alias);
                tmp.put(col, aliases);
            }
        }
        final NameCompleter completer = new NameCompleter();
        for (Entry<String, Set<String>> entry : tmp.entrySet()) {
            final String col = entry.getKey();
            final Set<String> aliases = entry.getValue();
            if (aliases.size() == 1) {
                completer.addName(col);
            } else {
                for (String name : aliases) {
                    completer.addName(name);
                }
            }
        }
        return completer.getAlternatives(lastWord);
    } else {
        // table completion.
        return _tableCompleter.completeTableName(HenPlus.getInstance().getCurrentSession(), lastWord);
    }
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) ResultSet(java.sql.ResultSet) HashMap(java.util.HashMap) NameCompleter(henplus.view.util.NameCompleter)

Example 4 with NameCompleter

use of henplus.view.util.NameCompleter in project henplus by neurolabs.

the class ListUserObjectsCommand method getAllColumnsCompleter.

private NameCompleter getAllColumnsCompleter(final SQLSession session) {
    NameCompleter compl = _sessionColumns.get(session);
    if (compl != null) {
        return compl;
    }
    /*
         * This may be a lengthy process..
         */
    _interrupted = false;
    SigIntHandler.getInstance().pushInterruptable(this);
    final NameCompleter tables = getTableCompleter(session);
    if (tables == null) {
        return null;
    }
    final Iterator<String> table = tables.getAllNamesIterator();
    compl = new NameCompleter();
    while (!_interrupted && table.hasNext()) {
        final String tabName = table.next();
        final Collection<String> columns = columnsFor(tabName);
        final Iterator<String> cit = columns.iterator();
        while (cit.hasNext()) {
            final String col = cit.next();
            compl.addName(col);
        }
    }
    if (_interrupted) {
        compl = null;
    } else {
        _sessionColumns.put(session, compl);
    }
    SigIntHandler.getInstance().popInterruptable();
    return compl;
}
Also used : NameCompleter(henplus.view.util.NameCompleter)

Example 5 with NameCompleter

use of henplus.view.util.NameCompleter in project henplus by neurolabs.

the class ListUserObjectsCommand method rehash.

/**
     * rehash table names.
     */
private NameCompleter rehash(final SQLSession session) {
    final NameCompleter result = new NameCompleter();
    // use createStmt
    final Connection conn = session.getConnection();
    ResultSet rset = null;
    try {
        final DatabaseMetaData meta = conn.getMetaData();
        rset = meta.getTables(null, null, null, LIST_TABLES_VIEWS);
        while (rset.next()) {
            result.addName(rset.getString(3));
        }
    } catch (final Exception e) {
    // ignore.
    } finally {
        if (rset != null) {
            try {
                rset.close();
            } catch (final Exception e) {
            }
        }
    }
    _sessionTables.put(session, result);
    _sessionColumns.remove(session);
    return result;
}
Also used : NameCompleter(henplus.view.util.NameCompleter) Connection(java.sql.Connection) ResultSet(java.sql.ResultSet) DatabaseMetaData(java.sql.DatabaseMetaData)

Aggregations

NameCompleter (henplus.view.util.NameCompleter)8 HashSet (java.util.HashSet)4 SQLSession (henplus.SQLSession)2 ResultSet (java.sql.ResultSet)2 LinkedHashSet (java.util.LinkedHashSet)2 StringTokenizer (java.util.StringTokenizer)2 SQLMetaData (henplus.SQLMetaData)1 SQLMetaDataBuilder (henplus.SQLMetaDataBuilder)1 SessionManager (henplus.SessionManager)1 ListUserObjectsCommand (henplus.commands.ListUserObjectsCommand)1 Table (henplus.sqlmodel.Table)1 DependencyResolver (henplus.util.DependencyResolver)1 ResolverResult (henplus.util.DependencyResolver.ResolverResult)1 IOException (java.io.IOException)1 PrintStream (java.io.PrintStream)1 Connection (java.sql.Connection)1 DatabaseMetaData (java.sql.DatabaseMetaData)1 SQLException (java.sql.SQLException)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1