⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 commandselect.java

📁 這是一個油Java實作的資料庫系統 是個入門的好材料
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* =============================================================
 * SmallSQL : a free Java DBMS library for the Java(tm) platform
 * =============================================================
 *
 * (C) Copyright 2004-2007, by Volker Berlin.
 *
 * Project Info:  http://www.smallsql.de/
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
 * USA.  
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 *
 * ---------------
 * CommandSelect.java
 * ---------------
 * Author: Volker Berlin
 * 
 */
package smallsql.database;

import java.sql.*;
import smallsql.database.language.Language;

class CommandSelect extends Command{

    private DataSources tables; // List of TableResult (Tables and Views)
	private Expression where;
    RowSource from;
    private Expressions groupBy;
    private Expression having;
    private Expressions orderBy;
    private boolean isAggregateFunction;
    private int maxRows = -1;
    /** is set if the keyword DISTINCT is used */
    private boolean isDistinct; 

    CommandSelect(Logger log){
		super(log);
    }
    
	CommandSelect(Logger log, Expressions columnExpressions){
		super(log, columnExpressions);
	}
    
    
    boolean compile(SSConnection con) throws Exception{
        boolean needCompile = false;
        if(tables != null){
            for(int i=0; i<tables.size(); i++){
				DataSource fromEntry = tables.get(i);
                needCompile |= fromEntry.init( con );
            }
        }

		if(from == null){
			from = new NoFromResult();
			tables = new DataSources();
			needCompile = true;
		}
        if(!needCompile) return false;

        for(int i=0; i<columnExpressions.size(); i++){
            Expression col = columnExpressions.get(i);
            if(col.getAlias() == null){
                // generate automate names for expressions
                col.setAlias("col" + (i+1));
            }

            if(col.getType() != Expression.NAME){
                compileLinkExpressionParams(col);
                continue;
            }

            ExpressionName expr = (ExpressionName)col;

            if("*".equals( expr.getName() )){
                String tableAlias = expr.getTableAlias();
                if(tableAlias != null){
                    // Syntax: tableAlias.*
                    int t=0;
                    for(; t<tables.size(); t++){
						DataSource fromEntry = tables.get(t);
                        if(tableAlias.equalsIgnoreCase( fromEntry.getAlias() )){
                            TableView table = fromEntry.getTableView();
                            columnExpressions.remove(i);
                            i = compileAdd_All_Table_Columns( fromEntry, table, i ) - 1;
                            break;
                        }
                    }
                    if(t==tables.size()) throw SmallSQLException.create(Language.COL_WRONG_PREFIX, new Object[] {tableAlias});
                }else{
                    // Syntax *
                    columnExpressions.remove(i);
                    for(int t=0; t<tables.size(); t++){
						DataSource fromEntry = tables.get(t);
                        TableView table = fromEntry.getTableView();
                        i = compileAdd_All_Table_Columns( fromEntry, table, i );
                    }
                    i--;
                }
            }else{
            	// not a * Syntax
                compileLinkExpressionName( expr );
            }

        }
        if(where != null) compileLinkExpression( where );
        if(having != null) compileLinkExpression( having );
        if(orderBy != null) {
            for(int i=0; i<orderBy.size(); i++){
            	compileLinkExpression( orderBy.get(i));
            }
        }
		if(groupBy != null){
			for(int i=0; i<groupBy.size(); i++){
				compileLinkExpression( groupBy.get(i) );
			}
		}

        if(from instanceof Join){
            compileJoin( (Join)from );
        }
        
        if(where != null){
        	from = new Where( from, where );
        }
        
		if(isGroupResult()) {
			from = new GroupResult( this, from, groupBy, having, orderBy);
			if(having != null){
                from = new Where( from, having );
            }
		}
		
		if(isDistinct){
			from = new Distinct( from, columnExpressions );
		}
		
		if(orderBy != null){
			from = new SortedResult( from, orderBy );
		}
		
		return true;
    }

    
    /**
     * If this ResultSet is use any type of grouping. This means that GroupResult need create and that
     * the ResultSet is not updatable. 
     */
    final boolean isGroupResult(){
    	return groupBy != null || having != null || isAggregateFunction;
    }
    
    
	/**
	 * Set the link between the Named Expression and the Table object
	 * in the condition.
	 * If there are cascade Joins then follow the tree with a recursion. 
	 */
    private void compileJoin( Join singleJoin ) throws Exception{
        if(singleJoin.condition != null) compileLinkExpressionParams( singleJoin.condition );
        if(singleJoin.left instanceof Join){
            compileJoin( (Join)singleJoin.left );
        }
        if(singleJoin.right instanceof Join){
            compileJoin( (Join)singleJoin.right );
        }
    }
    
    
    private void compileLinkExpression( Expression expr) throws Exception{
		if(expr.getType() == Expression.NAME)
			 compileLinkExpressionName( (ExpressionName)expr);
		else compileLinkExpressionParams( expr );
    }
    
    
    /**
     * Set the connection (link) of a named Expression to the table and the column index.
     * This means a column name in the SQL statement is link to it table source.
     */
    private void compileLinkExpressionName(ExpressionName expr) throws Exception{
        String tableAlias = expr.getTableAlias();
        if(tableAlias != null){
            int t = 0;
            for(; t < tables.size(); t++){
                DataSource fromEntry = tables.get(t);
                if(tableAlias.equalsIgnoreCase(fromEntry.getAlias())){
                    TableView table = fromEntry.getTableView();
                    int colIdx = table.findColumnIdx(expr.getName());
                    if(colIdx >= 0){
                        // Column was find and now we set the DataSouce, column index and TableView.
                        expr.setFrom(fromEntry, colIdx, table);
                        break;
                    }else
                        throw SmallSQLException.create(Language.COL_INVALID_NAME, new Object[]{expr.getName()});
                }
            }
            if(t == tables.size())
                throw SmallSQLException.create(Language.COL_WRONG_PREFIX, tableAlias);
        }else{
            // column name without table name
            boolean isSetFrom = false;
            for(int t = 0; t < tables.size(); t++){
                DataSource fromEntry = tables.get(t);
                TableView table = fromEntry.getTableView();
                int colIdx = table.findColumnIdx(expr.getName());
                if(colIdx >= 0){
                    if(isSetFrom){
                        // Column was already set. This means the column is ambiguous
                        throw SmallSQLException.create(Language.COL_AMBIGUOUS, expr.getName());
                    }
                    // Column was find and now we set the DataSouce, column index and TableView.
                    isSetFrom = true;
                    expr.setFrom(fromEntry, colIdx, table);
                }
            }
            if(!isSetFrom){
                throw SmallSQLException.create(Language.COL_INVALID_NAME, expr.getName());
            }
        }
        compileLinkExpressionParams(expr);
    }
    

    private void compileLinkExpressionParams(Expression expr) throws Exception{
        // check sub Expression (parameters)
        Expression[] expParams = expr.getParams();
		isAggregateFunction = isAggregateFunction || expr.getType() >= Expression.GROUP_BEGIN;
        if(expParams != null){
            for(int k=0; k<expParams.length; k++){
                Expression param = expParams[k];
				int paramType = param.getType();
				isAggregateFunction = isAggregateFunction || paramType >= Expression.GROUP_BEGIN;
                if(paramType == Expression.NAME)
                     compileLinkExpressionName( (ExpressionName)param );
                else compileLinkExpressionParams( param );
            }
        }
        expr.optimize();
    }
    

    private final int compileAdd_All_Table_Columns( DataSource fromEntry, TableView table, int position){
        for(int k=0; k<table.columns.size(); k++){
            ExpressionName expr = new ExpressionName( table.columns.get(k).getName() );
            expr.setFrom( fromEntry, k, table );
            columnExpressions.add( position++, expr );
        }
        return position;
    }
    

    /**
     * The main method to execute this Command and create a ResultSet.
     */
    void executeImpl(SSConnection con, SSStatement st) throws Exception{
        compile(con);
        if((st.rsType == ResultSet.TYPE_SCROLL_INSENSITIVE || st.rsType == ResultSet.TYPE_SCROLL_SENSITIVE) &&
        	!from.isScrollable()){
        	from = new Scrollable(from);
        }
        from.execute();
        rs =  new SSResultSet( st, this );
    }
    
    
    /**
     * Is used from ResultSet.beforeFirst().
     *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -