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);
}
|