[Squirrel-sql-commits] sql12/app/src/net/sourceforge/squirrel_sql/client/session/parser/kernel/compl
A Java SQL client for any JDBC compliant database
Brought to you by:
colbell,
gerdwagner
From: Colin B. <co...@us...> - 2004-04-04 10:48:58
|
Update of /cvsroot/squirrel-sql/sql12/app/src/net/sourceforge/squirrel_sql/client/session/parser/kernel/completions In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31947/app/src/net/sourceforge/squirrel_sql/client/session/parser/kernel/completions Added Files: ErrorListener.java SQLColumn.java SQLModifyingStatement.java SQLSelectStatement.java SQLSelectStatementListener.java SQLStatement.java SQLStatementContext.java SQLTable.java SQLWhere.java Log Message: Gerd Wagners patch - adds SQL parser --- NEW FILE: SQLModifyingStatement.java --- /* * net.sourceforge.squirrel_sql.client.session.parser.kernel.completions.SQLModifyingStatement * * created by cse, 11.10.2002 17:14:06 * * Copyright (c) 2002 DynaBEAN Consulting, all rights reserved */ package net.sourceforge.squirrel_sql.client.session.parser.kernel.completions; import net.sourceforge.squirrel_sql.client.session.parser.kernel.SQLSchema; import net.sourceforge.squirrel_sql.client.session.parser.kernel.Completion; import net.sourceforge.squirrel_sql.client.session.parser.kernel.ParserLogger; import java.util.List; import java.util.ArrayList; import java.util.Iterator; /** * an SQL statement class representing modyfing statements, i.e. * INSERT, UPDATE and DELETE. The important common trait of these statements * is that they alow for only one target table to be specified */ public class SQLModifyingStatement extends SQLStatement { private SQLTable m_table; private int updateListStart = NO_POSITION; private int updateListEnd = NO_POSITION; public SQLModifyingStatement(int start) { super(start); } public List getTables(String catalog, String schema, String name) { if(name != null || m_table == null) { return super.getTables(catalog, schema, name); } else { List tables = super.getTables(m_table.catalog, m_table.schema, m_table.name); List result = new ArrayList(); Iterator it = tables.iterator(); while(it.hasNext()) { Table table = (Table)it.next(); if(table.matches(catalog, schema, name)) result.add(table); } return result; } } public void addTable(SQLTable table) { super.addTable(table); m_table = table; } public SQLSchema.Table getTable() { return getTable(m_table.catalog, m_table.schema, m_table.name); } public boolean setTable(String catalog, String schema, String name, String alias) { return super.setTable(catalog, schema, name, alias); } public void setUpdateListStart(int position) { ParserLogger.log("updateListStart: "+position); updateListStart = position; updateListEnd = NO_LIMIT; } public void setUpdateListEnd(int position) { updateListEnd = position; } public Completion getCompletion(int position) { Completion c = super.getCompletion(position); if(c == null) { if(position >= updateListStart && position <= updateListEnd) { SQLColumn col = new SQLColumn(this, position); col.setRepeatable(false); return col; } } return c; } } --- NEW FILE: SQLTable.java --- /* * Copyright (C) 2002 Christian Sell * cs...@us... * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * created by cse, 27.09.2002 20:15:39 */ package net.sourceforge.squirrel_sql.client.session.parser.kernel.completions; import net.sourceforge.squirrel_sql.client.session.parser.kernel.SQLCompletion; import net.sourceforge.squirrel_sql.client.session.parser.kernel.SQLSchema; import net.sourceforge.squirrel_sql.client.session.parser.kernel.ParserLogger; import java.util.List; import java.util.Collections; /** * this class represents a table completion, as it appears within the FROM * clause of a a select statement, and in other places.<br> * <em>Note: do not confuse with SQLSchema.Table</em> */ public class SQLTable extends SQLCompletion { public String catalog; public String schema; public String name; public String alias; private SQLStatement statement; public SQLTable(SQLStatement statement, int start) { super(start); ParserLogger.log("SQLTable: "+start); this.statement = statement; } public SQLTable(SQLStatement statement, int start, int end) { super(start); ParserLogger.log("SQLTable: "+start+" "+end); this.statement = statement; setEndPosition(end); } public SQLStatement getStatement() { return statement; } public void setCatalog(String catalog, int pos) { this.catalog = catalog; setEndPosition(pos+catalog.length()-1); } public void setSchema(String schema, int pos) { this.schema = schema; setEndPosition(pos+schema.length()-1); } public void setName(String name, int pos) { this.name = name; setEndPosition(pos+name.length()-1); } public void setAlias(String alias, int pos) { this.alias = alias; setEndPosition(pos+alias.length()-1); } public SQLSchema.Table[] getCompletions(int position) { String tb = (name != null && position > startPosition) ? name.substring(0, position - startPosition) : null; List tables = getStatement().getTables(catalog, schema, tb); Collections.sort(tables); return (SQLSchema.Table[])tables.toArray(new SQLSchema.Table[tables.size()]); } /** * @return true if the name is set */ protected boolean isConcrete() { return name != null; } /** * tables are safe to repeat, as they only appear in the from clause * @return <em>true</em> */ public boolean isRepeatable() { return true; } public boolean mustReplace(int position) { return name != null && position >= startPosition && position <= endPosition; } public String getText(int position, String option) { return option; } } --- NEW FILE: SQLStatementContext.java --- /* * net.sourceforge.squirrel_sql.client.session.parser.kernel.completions.SQLStatementContext * * created by cse, 10.10.2002 16:49:35 * * Copyright (c) 2002 DynaBEAN Consulting, all rights reserved */ package net.sourceforge.squirrel_sql.client.session.parser.kernel.completions; import net.sourceforge.squirrel_sql.client.session.parser.kernel.Completion; import net.sourceforge.squirrel_sql.client.session.parser.kernel.SQLSchema; /** * a context which gives access to the nearest statement */ public interface SQLStatementContext extends Completion { SQLStatement getStatement(); void setSqlSchema(SQLSchema schema); void addContext(SQLStatementContext context); void addColumn(SQLColumn column); } --- NEW FILE: SQLStatement.java --- /* * Copyright (C) 2002 Christian Sell * cs...@us... * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * created 24.09.2002 12:27:12 * * @version $Id: SQLStatement.java,v 1.1 2004/04/04 10:36:30 colbell Exp $ */ package net.sourceforge.squirrel_sql.client.session.parser.kernel.completions; import net.sourceforge.squirrel_sql.client.session.parser.kernel.SQLCompletion; import net.sourceforge.squirrel_sql.client.session.parser.kernel.SQLSchema; import net.sourceforge.squirrel_sql.client.session.parser.kernel.Completion; import java.util.*; /** * a completion representing a full SQl statement. This object servers only * as a container for subelements, thus constituting a completion context. */ public class SQLStatement extends SQLCompletion implements SQLSchema, SQLStatementContext { private SortedSet children; protected SQLSchema sqlSchema; public SQLStatement(int start) { super(start); } /** * @param position the position at which the completion should be inserted * @return the available completion */ public Completion getCompletion(int position) { if(isEnclosed(position)) { Iterator it = getChildren(); while(it.hasNext()) { Completion c = ((Completion)it.next()).getCompletion(position); if(c != null) return c; } } return null; } public void setSqlSchema(SQLSchema schema) { if(schema == this) throw new RuntimeException("internal error: recursive schema"); this.sqlSchema = schema; } protected void addChild(Completion child) { if(children == null) children = new TreeSet(new ChildComparator()); children.add(child); } public void addContext(SQLStatementContext context) { context.setSqlSchema(this); addChild(context); } public void setEndPosition(int offset) { super.setEndPosition(offset); if(sqlSchema instanceof SQLStatement) ((SQLStatement)sqlSchema).setEndPosition(offset); } public void addTable(SQLTable table) { addChild(table); } public boolean setTable(SQLTable table) { return setTable(table.catalog, table.schema, table.name, table.alias); } /** * take note of table usage, validating it against the underlying schema. * @param catalog catalog name (otional) * @param schema schema name (optional) * @param name table name (required) * @param alias alias (unused) * @return true if the table is valid */ public boolean setTable(String catalog, String schema, String name, String alias) { return sqlSchema.getTable(catalog, schema, name) != null; } public Table getTable(String catalog, String schema, String name) { return sqlSchema.getTable(catalog, schema, name); } public List getTables(String catalog, String schema, String name) { return sqlSchema.getTables(catalog, schema, name); } public Table getTableForAlias(String alias) { return sqlSchema.getTableForAlias(alias); } public void addColumn(SQLColumn column) { addChild(column); } public SQLStatement getStatement() { return this; } protected Iterator getChildren() { return children != null ? children.iterator() : Collections.EMPTY_LIST.iterator(); } /** * @return the unique table assigned to this statement, or <em>null</em> if this statement * can hold multiple tables, or no table was assigned. By default, <em>null</em>. */ public Table getTable() { return null; } } --- NEW FILE: SQLSelectStatement.java --- /* * Copyright (C) 2002 Christian Sell * cs...@us... * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * created by cse, 26.09.2002 15:14:45 * * @version $Id: SQLSelectStatement.java,v 1.1 2004/04/04 10:36:30 colbell Exp $ */ package net.sourceforge.squirrel_sql.client.session.parser.kernel.completions; import net.sourceforge.squirrel_sql.client.session.parser.kernel.SQLSchema; import net.sourceforge.squirrel_sql.client.session.parser.kernel.Completion; import net.sourceforge.squirrel_sql.client.session.parser.kernel.ParserLogger; import java.util.Map; import java.util.HashMap; import java.util.List; import java.util.Vector; /** * an SQL select statement */ public class SQLSelectStatement extends SQLStatement { private static final int FA_START = 0; private static final int FA_END = 1; private static final int FA_GROUPBY = 0; private static final int FA_HAVING = 1; private static final int FA_ORDERBY = 2; private Map aliasMap = new HashMap(); private int selectListStart, selectListEnd, fromStart, fromEnd; private int[][] fieldAreas = new int[3][2]; //FA_xxx private Vector listeners = new Vector(); public SQLSelectStatement(int start) { super(start); } public void setSelectListStart(int start) { selectListStart = start; selectListEnd = NO_LIMIT; setEndPosition(selectListEnd); } public void setSelectListEnd(int end) { selectListEnd = end; setEndPosition(end); } public void setFromStart(int fromStart) { this.fromStart = fromStart; this.fromEnd = NO_LIMIT; setEndPosition(fromEnd); } public void setFromEnd(int fromEnd) { this.fromEnd = fromEnd; setEndPosition(fromEnd); } public void setGroupByStart(int start) { setFieldAreaStart(FA_GROUPBY, start); } public void setGroupByEnd(int whereEnd) { setFieldAreEnd(FA_GROUPBY, whereEnd); } public void setHavingStart(int start) { setFieldAreaStart(FA_HAVING, start); } public void setHavingEnd(int whereEnd) { setFieldAreEnd(FA_HAVING, whereEnd); } public void setOrderByStart(int start) { setFieldAreaStart(FA_ORDERBY, start); } public void setOrderByEnd(int whereEnd) { setFieldAreEnd(FA_ORDERBY, whereEnd); } private void setFieldAreaStart(int fa, int start) { fieldAreas[fa][FA_START] = start; fieldAreas[fa][FA_END] = NO_LIMIT; setEndPosition(NO_LIMIT); } private void setFieldAreEnd(int fa, int end) { fieldAreas[fa][FA_END] = end; setEndPosition(end); } public boolean setTable(String catalog, String schema, String name, String alias) { ParserLogger.log("setTable: "+alias+"."+name); Table table = sqlSchema.getTable(catalog, schema, name); if(table == null) return false; if(alias != null) { aliasMap.put(alias, table.clone(alias)); fireAliasDefined(name, alias); } return true; } public List getTables(String catalog, String schema, String name) { if(aliasMap.size() == 0) return sqlSchema.getTables(catalog, schema, name); else { List tables = sqlSchema.getTables(catalog, schema, name); tables.addAll(aliasMap.values()); return tables; } } public SQLSchema.Table getTableForAlias(String alias) { SQLSchema.Table table = (SQLSchema.Table)aliasMap.get(alias); return table != null ? table : sqlSchema.getTableForAlias(alias); } public Completion getCompletion(int offset) { Completion comp = super.getCompletion(offset); if(comp != null) return comp; if(offset >= selectListStart && offset <= selectListEnd) return new SQLColumn(this, offset, offset); else if(offset >= fromStart && offset <= fromEnd) return new SQLTable(this, offset, offset); else { for(int i=0; i<fieldAreas.length; i++) { if(offset >= fieldAreas[i][FA_START] && offset <= fieldAreas[i][FA_END]) { SQLColumn col = new SQLColumn(this, offset, offset); col.setRepeatable(false); return col; } } } return null; } public void addListener(SQLSelectStatementListener l) { listeners.add(l); } public void removeListener(SQLSelectStatementListener l) { listeners.remove(l); } private void fireAliasDefined(String tableName, String aliasName) { SQLSelectStatementListener[] clone = (SQLSelectStatementListener[]) listeners.toArray(new SQLSelectStatementListener[listeners.size()]); for (int i = 0; i < clone.length; i++) { clone[i].aliasDefined(tableName, aliasName); } } } --- NEW FILE: SQLWhere.java --- /* * Copyright (C) 2002 Christian Sell * cs...@us... * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * created by cse, 10.10.2002 14:29:20 * * @version $Id: SQLWhere.java,v 1.1 2004/04/04 10:36:30 colbell Exp $ */ package net.sourceforge.squirrel_sql.client.session.parser.kernel.completions; import net.sourceforge.squirrel_sql.client.session.parser.kernel.SQLCompletion; import net.sourceforge.squirrel_sql.client.session.parser.kernel.Completion; import net.sourceforge.squirrel_sql.client.session.parser.kernel.SQLSchema; import java.util.List; import java.util.ArrayList; import java.util.Iterator; /** * a completion which represents the WHERE clause inside SELECT, UPDATE or DLETE * statements */ public class SQLWhere extends SQLCompletion implements SQLStatementContext { private SQLStatement statement; private List children = new ArrayList(); public SQLWhere(SQLStatement statement, int startPosition) { super(startPosition); this.statement = statement; setEndPosition(NO_LIMIT); } public void setEndPosition(int position) { statement.setEndPosition(position); super.setEndPosition(position); } public Completion getCompletion(int position) { if(super.getCompletion(position) != null) { Iterator it = children.iterator(); while(it.hasNext()) { Completion comp = (Completion)it.next(); if((comp = comp.getCompletion(position)) != null) return comp; } SQLColumn col = new SQLColumn(this, position); col.setRepeatable(false); return col; } return null; } public SQLStatement getStatement() { return statement; } public void setSqlSchema(SQLSchema schema) { //schema should be identical to the statement. Ignore } public void addContext(SQLStatementContext context) { context.setSqlSchema(statement); children.add(context); } public void addColumn(SQLColumn column) { children.add(column); } } --- NEW FILE: SQLSelectStatementListener.java --- package net.sourceforge.squirrel_sql.client.session.parser.kernel.completions; public interface SQLSelectStatementListener { void aliasDefined(String tableName, String aliasName); } --- NEW FILE: SQLColumn.java --- /* * Copyright (C) 2002 Christian Sell * cs...@us... * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * created by cse, 24.09.2002 16:00:59 * * @version $Id: SQLColumn.java,v 1.1 2004/04/04 10:36:30 colbell Exp $ */ package net.sourceforge.squirrel_sql.client.session.parser.kernel.completions; import net.sourceforge.squirrel_sql.client.session.parser.kernel.SQLCompletion; import net.sourceforge.squirrel_sql.client.session.parser.kernel.SQLSchema; import net.sourceforge.squirrel_sql.client.session.parser.kernel.ParserLogger; /** * a completion suggesting column names */ public class SQLColumn extends SQLCompletion { private String name; private String qualifier; private boolean isRepeatable = true; private SQLStatementContext parent; private int namePos = NO_POSITION; public SQLColumn(SQLStatementContext parent, int start) { super(start); this.parent = parent; } public SQLColumn(SQLStatementContext parent, int start, int end) { super(start); this.parent = parent; setEndPosition(end); } public SQLColumn(SQLStatementContext parent) { super(); this.parent = parent; } public void setQualifier(String alias, int pos) { this.qualifier = alias; this.namePos = pos+alias.length()+1; setEndPosition(namePos); ParserLogger.log("setAlias: s="+startPosition+" e="+endPosition); } public void setQualifier(String alias) { this.qualifier = alias; } public String getQualifier() { return qualifier; } public void setColumn(String name, int pos) { this.name = name; this.namePos = pos; setEndPosition(pos+name.length()-1); } public void setName(String name) { this.name = name; } public String getName() { return name; } /** * check whether a table assignment exists at the given cursor position. A table assignment * exists in the following cases:<br> * <ul><li>if the parent statement has only one table</li> * <li>if the cursor is placed immediately after the qualifier separator. It does not * exist if the column is not qualified (by alias or table name), or if the cursor is placed * inside the qualifier.</li> * @param position the caret position * @return whether a table assignment exists */ public boolean hasTable(int position) { return (qualifier == null && parent.getStatement().getTable() != null) || (qualifier != null && position >= namePos && position <= endPosition && parent.getStatement().getTableForAlias(qualifier) != null); } public SQLStatement getStatement() { return parent.getStatement(); } public String getText() { String text = qualifier != null ? qualifier+"."+name : name; if(hasTextPosition()) { int oldDataPos = endPosition - startPosition; return text.substring(oldDataPos, text.length()); } else { return text; } } /** * @return true if the name is set */ protected boolean isConcrete() { return name != null; } public String getText(int position) { return getText(position, name); } public String getText(int position, String option) { if(position == endPosition) { return option; } else if(mustReplace(position) || isOther(position)) { return qualifier != null ? qualifier+"."+option : option; } else { String text = qualifier != null ? qualifier+"."+option : option; int oldDataPos = endPosition - position; return text.substring(oldDataPos, text.length()); } } // check if this completion request is outside the original definition point private boolean isOther(int position) { return endPosition == NO_LIMIT || position < startPosition || position > endPosition; } public String[] getCompletions(int position) { SQLSchema.Table table = null; if(qualifier != null) { // try as an alias table = getStatement().getTableForAlias(qualifier); // could also be a table name if(table == null) table = getStatement().getTable(null, null, qualifier); } else // see if its a one-table statement table = getStatement().getTable(); // now match the columns if(table != null) { String col = null; if(name != null && position > namePos) { col = position <= endPosition ? name.substring(0, position-namePos) : name; } String[] result = table.getColumns(col); return (col != null && result.length == 1 && result[0].length() == col.length()) ? EMPTY_RESULT : result; //no need to return if completion is identical } else return EMPTY_RESULT; } public void setRepeatable(boolean repeatable) { isRepeatable = repeatable; } public boolean isRepeatable() { return isRepeatable; } public boolean mustReplace(int position) { return name != null && position >= startPosition && position <= endPosition; } } --- NEW FILE: ErrorListener.java --- package net.sourceforge.squirrel_sql.client.session.parser.kernel.completions; public interface ErrorListener { void errorDetected(String message, int line, int column); } |